home *** CD-ROM | disk | FTP | other *** search
/ Aminet 19 / Aminet 19 (1997)(GTI - Schatztruhe)[!][Jun 1997].iso / Aminet / dev / misc / FD2Pragma.lha / Source / FD2Pragma.c next >
Encoding:
C/C++ Source or Header  |  1997-03-27  |  70.9 KB  |  2,933 lines

  1. #define NAME     "FD2Pragma"
  2. #define VERSION  "2"
  3. #define REVISION "35"
  4. #define ENDCODE
  5. //#define DEBUG
  6. //#define DEBUG_OLD
  7.  
  8. /* Programmheader
  9.  
  10.     Name:        FD2Pragma
  11.     Author:        SDI
  12.     Distribution:    PD
  13.     Description:    creates pragmas files, lvo files and stub functions
  14.     Compileropts:    -
  15.     Linkeropts:    -gd
  16.     Bugs:        CLIB scan does not recognize functions getting a
  17.             function as parameter, CPP name for functions:
  18.             'PF' <returnvalue> <parameters> 'p'
  19.  
  20.  1.2    : added pragmas for the Dice compiler. Available via switch "Dice".
  21.     added switches "Aztec", "SAS" and "Maxon": Maxon and Aztec just
  22.     turn on the default (except that Maxon expects pragma files to be
  23.     called "xxx_pragmas.h" instead of "xxx_lib.h"), SAS is equal to
  24.     Dice, except that SAS supports the pragma tagcall.
  25.  2.0    : Added support for tag functions. See the docs for details.
  26.      Author until this version:
  27.         Jochen Wiedmann
  28.     Am Eisteich 9
  29.     72555 Metzingen (Germany)
  30.     Tel. 07123 / 14881
  31.     E-Mail: wiedmann@mailserv.zdv.uni-tuebingen.de
  32.  2.1   19.08.96 : now made by SDI, added correct __MAXON__ support and
  33.      support for StormC++, added auto recognition of tagcall functions
  34.      changed the CLI interface completely
  35.  2.2   21.08.96 : fixed a lot of errors, added debug code
  36.  2.3   22.08.96 : little changes
  37.  2.4   24.08.96 : added proto-file creation
  38.  2.5   25.08.96 : added syscall and fix for functions ending in ...DMA
  39.  2.6   26.08.96 : fixed some errors, added CLIB parameter (used later for
  40.     CSTUBS)
  41.  2.7   01.09.96 : added correct Storm definition, added CLIB scan
  42.  2.8   02.09.96 : added assembler stub functions, added first ASM-stub code
  43.  2.9   04.09.96 : added Comment-Support
  44.  2.10  05.09.96 : changed CSTUB creation a bit
  45.  2.11  07.09.96 : speeded up output, reduced number of strndup calls
  46.  2.12  26.09.96 : pressing CTRL-C in early startup brought an wrong error
  47.     message - fixed
  48.  2.13  30.09.96 : made RegNames field to RegNames string - shorter Exe-file
  49.  2.14  01.10.96 : made SPECIAL 6 default, COMMENT also in LVO files
  50.  2.15  13.10.96 : corrected an error text
  51.  2.16  14.10.96 : added correct comment support and PRIVATE option
  52.  2.17  19.10.96 : now Maxon-compiled in Small data mode
  53.  2.18  22.10.96 : removed EXTERNC in Storm, Maxon and all pragmas, corrected
  54.     the texts
  55.  2.19  26.10.96 : added option to create FD files out of pragma files,
  56.     reworked a lot in the source
  57.  2.20  27.10.96 : fixed errors of previous version
  58.  2.21  28.10.96 : fixed error im CLIB scan
  59.  2.22  27.11.96 : SPECIAL numbers for lib and ASM code were wrong, removed
  60.      bug in Tag function stubs
  61.  2.23  06.12.96 : lib and stub creation still was wrong
  62.  2.24  31.12.96 : formed stub libs matching C++ file names, corrected CLIB
  63.      scan errors
  64.  2.25  04.01.97 : added HEADER option (I was asked for)
  65.  2.26  05.01.97 : added HEADER scan (in old file) and auto inserting
  66.  2.27  10.01.97 : stub functions missed register saving, outfuncs skip now,
  67.      when error occured (makes lots of error checking obsolete)
  68.  2.28  11.01.97 : forgot to add offset made by register saving
  69.  2.29  18.01.97 : now libtags and amitags defines only, when at least 1
  70.      tagfunc
  71.  2.30  13.02.97 : added local library base functions, rearranged SPECIAL
  72.            options, fixed some bugs
  73.  2.31  15.02.97 : corrected bugs inserted in previous version
  74.  2.32  16.02.97 : and again bug fixes, still didn't work
  75.  2.33  18.02.97 : corrected texts, added SPECIAL 28
  76.  2.34  25.03.97 : corrected Pragma --> FD file conversion, added ##shadow
  77.  2.35  26.07.97 : added STORMFD option, COMMENT, PRIVATE work again
  78. */
  79.  
  80. #include <exec/memory.h>
  81. #include <dos/doshunks.h>
  82.  
  83. #include <pragma/exec_lib.h>
  84. #include <pragma/dos_lib.h>
  85. #include <pragma/intuition_lib.h>
  86.  
  87. #define SDI_TO_ANSI
  88. #include "SDI_ASM_STD_protos.h"
  89. #include "SDI_defines.h"
  90. #include "SDI_structures.h"
  91.  
  92. #define TEXT_SAS    "__SASC"    // verified
  93. #define TEXT_SAS_60    "__SASC_60"    // verified
  94. #define TEXT_MAXON    "__MAXON__"    // verified
  95. #define TEXT_STORM    "__STORM__"    // verified
  96. #define TEXT_DICE    "_DCC"        // in 2.0 code
  97. #define TEXT_AZTEC    "AZTEC_C"    // verified
  98. #define TEXT_GNUC    "__GNUC__"    // in 2.0 code
  99.  
  100. #define FLAG_EXTERNC    (1<<0)
  101. #define FLAG_PROTOTYPE    (1<<1) //dice
  102. #define FLAG_SYSCALL    (1<<2)
  103. #define FLAG_DOCOMMENT    (1<<3)
  104. #define FLAG_PRIVATE    (1<<4)
  105. #define FLAG_LOCALREG   (1<<5)
  106. #define FLAG_STORMFD    (1<<6)
  107.  
  108. #define MODUS_STUBTEXT    1
  109. #define MODUS_STUBCODE    2
  110. #define MODUS_LOCALDATA 3
  111. #define MODUS_LVO    4    // and 5 and 6 and 7
  112. #define MODUS_PROTO    8    // and 9 and 10 and 12
  113. #define MODUS_PRAGMA    13
  114. #define MODUS_ERROR    100
  115.  
  116. #define TAGMODE_NORMAL    0
  117. #define TAGMODE_TAGS    1
  118. #define TAGMODE_BOTH    2
  119.  
  120. #define PARAM "FDFILE/A,SPECIAL/N,TO/K,COMMENT/S,MODE/N,AMICALL/K,"     \
  121.     "LIBCALL/K,AMITAGS/K,LIBTAGS/K,CSTUBS/K,EXTERNC/S,USESYSCALL/S," \
  122.     "CLIB/K,PRIVATE/S,HEADER/K,STORMFD/S"
  123.  
  124. UBYTE RegNames[] =
  125. "d0\0\0" "d1\0\0" "d2\0\0" "d3\0\0" "d4\0\0" "d5\0\0" "d6\0\0" "d7\0\0"
  126. "a0\0\0" "a1\0\0" "a2\0\0" "a3\0\0" "a4\0\0" "a5\0\0" "a6\0\0" "a7";
  127. // double zero, to make the finding easier (by using <<2 instead of *3)
  128.  
  129. struct ShortList {
  130.   struct ShortList    *Next;
  131. };
  132.  
  133. struct ShortListRoot {
  134.   struct ShortList    *First;
  135.   struct ShortList    *Last;
  136.   ULONG            Size;
  137. };
  138.  
  139. struct AmiPragma {
  140.   struct ShortList    List;
  141.   UWORD            Bias;
  142.   UWORD            Public;
  143.   STRPTR        FuncName;
  144.   STRPTR        TagName;
  145.   UWORD            NumArgs;
  146.   struct AmiArgs
  147.   {
  148.     STRPTR        ArgName;
  149.     UWORD        ArgReg;
  150.   } Args[14];    /*  a6 and a7 must not be used for function arguments    */
  151. };
  152.  
  153. struct Comment {
  154.   struct ShortList    List;
  155.   STRPTR        Data;
  156.   UWORD            Bias;
  157. };
  158.  
  159. struct PragList {
  160.   struct ShortList    List;
  161.   STRPTR        Basename;
  162.   struct ShortListRoot    Data;
  163. };
  164.  
  165. struct PragData {
  166.   struct ShortList    List;
  167.   ULONG            NumNames;
  168.   ULONG            NumArgs;
  169.   UBYTE            ArgReg[14];
  170.   ULONG            Bias;
  171.   struct ShortListRoot    Name;
  172. };
  173.  
  174. struct FDData {
  175.   STRPTR    Name;
  176.   STRPTR    Basename;
  177.   ULONG        NumArgs;
  178.   UBYTE        ArgReg[14];
  179.   ULONG        Bias;
  180.   ULONG        Mode;        // 0 = Normal, != 0 is TagName
  181. };
  182.  
  183. #define CPP_TYPE_VOID        'v'    // void,    VOID
  184. #define CPP_TYPE_BYTE        'c'    // char,    BYTE
  185. #define CPP_TYPE_WORD        's'    // short,    WORD
  186. #define CPP_TYPE_LONG        'j'    // long,    LONG
  187. #define CPP_TYPE_FLOAT        'f'    // float,    FLOAT
  188. #define CPP_TYPE_DOUBLE        'd'    // double,    DOUBLE
  189. #define CPP_TYPE_STRUCTURE    0
  190. #define CPP_TYPE_VARARGS    'e'
  191.  
  192. #define CPP_FLAG_UNSIGNED    (1<<0)
  193. #define CPP_FLAG_CONST        (1<<1)
  194. #define CPP_FLAG_STRPTR        (1<<2)
  195. #define CPP_FLAG_POINTER    (1<<3)
  196. /* STRPTR is defined different under C and CPP -> I have to create two
  197. names, one time unsigned char *, one time signed char *, when somewhere
  198. a STRPTR occurs */
  199.  
  200. struct CPP_NameType {
  201.   STRPTR    StructureName;     // if a structure only
  202.   UWORD        StructureLength; // length of the structure name
  203.   UBYTE        Type;         // see above defines
  204.   UBYTE        Flags;         // see above flags
  205.   UWORD        PointerDepth;     // number of * in type
  206. };  
  207.  
  208. struct CPP_TypeField {
  209.   STRPTR    Text;
  210.   UWORD        Length;
  211.   UBYTE        Flags;
  212.   UBYTE        Type;
  213. };
  214.  
  215. #define NTP_NORMAL    0    // no tags/args
  216. #define NTP_TAGS    1    // TagFunction
  217. #define NTP_ARGS    2    // ArgFunction
  218. #define NTP_UNKNOWN    3    // CommentFunction
  219.  
  220. struct NameList {
  221.   struct ShortList    List;
  222.   ULONG            Type; // set by OptimizeFDData
  223.   STRPTR        NormName;
  224.   STRPTR        PragName;
  225. };
  226.  
  227. struct RDArgs    *rda            = 0;
  228. struct SDI_InOut in            = {0,0,0,0,0},
  229.          out            = {0,0,5120,0,0};
  230. STRPTR        clibbuf            = 0;
  231. ULONG        clibsize        = 0;
  232. struct FileInfoBlock *fib        = 0;
  233. struct ShortListRoot    AmiPragma    = {0,0,sizeof(struct AmiPragma)},
  234.              Comment        = {0,0,sizeof(struct Comment)};
  235. struct Remember *remember        = 0;
  236. ULONG        oldfh            = 0;
  237. ULONG        lock            = 0;
  238. STRPTR        BaseName        = 0;
  239. STRPTR        ShortBaseName        = 0;
  240. STRPTR        ShortBaseNameUpper    = 0;
  241. ULONG        DosVersion        = 37; // force OS2.0
  242. ULONG        MODE            = 1;
  243. STRPTR        AMICALL            = 0;
  244. STRPTR        LIBCALL            = 0;
  245. STRPTR        AMITAGS            = 0;
  246. STRPTR        LIBTAGS            = 0;
  247. STRPTR        CSTUBS            = 0;
  248. STRPTR        HEADER            = 0;
  249. ULONG        headersize        = 0;
  250. ULONG        Flags            = 0;
  251. struct IntuitionBase *IntuitionBase    = 0;
  252. ULONG        Output_Error        = 1; // Output error occured when 0
  253. ULONG        tagfuncs        = 0; // are there some tagfuncs in FD
  254. UBYTE        deftype[]        = "ULONG";
  255.  
  256. /* Prototypes for the functions */
  257. STRPTR strndup(STRPTR, ULONG);
  258. void DoError(UBYTE, ULONG, ...);
  259. ULONG Out(ULONG);
  260. ULONG DoOutput(STRPTR, ...);
  261. ULONG DoOutputDirect(APTR, ULONG);
  262. STRPTR SkipBlanks(STRPTR);
  263. STRPTR SkipName(STRPTR);
  264. ULONG MakeTagFunction(struct AmiPragma *);
  265. void MakeLines(STRPTR, ULONG, ULONG);
  266. ULONG ScanFDFile(void);
  267. void FindHeader(void);
  268. ULONG GetRegisterData(struct AmiPragma *);
  269. ULONG OutputXDEF(STRPTR, ...);
  270. /* ------------------------------------------------------------------ */
  271. struct ShortList *NewItem(struct ShortListRoot *);
  272. struct ShortList *RemoveItem(struct ShortListRoot *, struct ShortList *);
  273. void          AddItem(struct ShortListRoot *, struct ShortList *);
  274. /* ------------------------------------------------------------------ */
  275. ULONG FuncAMICALL(struct AmiPragma *, ULONG);
  276. ULONG FuncLIBCALL(struct AmiPragma *, ULONG);
  277. ULONG FuncAsmText(struct AmiPragma *, ULONG);
  278. ULONG FuncAsmCode(struct AmiPragma *, ULONG);
  279. ULONG FuncCSTUBS (struct AmiPragma *, ULONG);
  280. ULONG FuncLVOXDEF(struct AmiPragma *, ULONG);
  281. ULONG FuncLVO    (struct AmiPragma *, ULONG);
  282. ULONG FuncLocCode(struct AmiPragma *, ULONG);
  283. ULONG FuncLocText(struct AmiPragma *, ULONG);
  284. ULONG CallFunc(ULONG, STRPTR, ULONG (*) (struct AmiPragma *, ULONG));
  285. /* ------------------------------------------------------------------ */
  286. ULONG CopyCPPType(STRPTR, STRPTR, ULONG, STRPTR, struct AmiArgs *);
  287. void GetCPPType(struct CPP_NameType *, STRPTR);
  288. STRPTR FindClibFunc(STRPTR);    // finds the needed function
  289. ULONG GetClibLength(STRPTR);    // returns length of the type
  290. ULONG OutClibType(STRPTR);
  291. STRPTR GetClibType(STRPTR);    // searches for next type definition
  292. /* ------------------------------------------------------------------ */
  293. ULONG CallPrag(ULONG, STRPTR, ULONG (*) (struct AmiPragma *, ULONG));
  294. ULONG CreatePragmaFile(void);
  295. ULONG CreateLVOFile(ULONG);
  296. ULONG CreateAsmStubs(ULONG);
  297. ULONG CreateProtoFile(ULONG);
  298. ULONG CreateLocalData(void);
  299. /* ------------------------------------------------------------------ */
  300. ULONG GetName(struct NameList *, struct ShortListRoot *, ULONG);
  301. ULONG MakeFD(struct PragList *);
  302. void OptimizeFDData(struct PragData *);
  303. UBYTE GetHexValue(UBYTE);
  304. ULONG AddFDData(struct ShortListRoot *, struct FDData *);
  305. ULONG GetLibData(struct FDData *);
  306. ULONG GetAmiData(struct FDData *);
  307. ULONG CreateFDFile(STRPTR, STRPTR);
  308. /* ------------------------------------------------------------------ */
  309. void main(void);
  310. void end(void);
  311.  
  312. STRPTR strndup(STRPTR Str, ULONG Len)
  313. {
  314.   STRPTR res;
  315.   if((res = (STRPTR) AllocRemember(&remember, Len+1, MEMF_ANY|MEMF_CLEAR)))
  316.   {
  317.     CopyMem(Str, res, Len);
  318.     res[Len] = '\0';
  319.   }
  320.   return res;
  321. }
  322.  
  323. enum {
  324. ERR_TAGFUNC_NEEDS_ARGUMENT,
  325. ERR_CANNOT_CONVERT_PRAGMA_TAGCALL,
  326. ERR_TAG_DEF_WITHOUT_PRAGMA,
  327. ERR_BASENAME_DECLARED_TWICE,
  328. ERR_EXPECTED_SLASH_IN_BASENAME,
  329. ERR_EXPECTED_BASENAME,
  330. ERR_EXPECTED_BIAS_VALUE,
  331. ERR_ASSUMING_POSITIVE_BIAS_VALUE,
  332. ERR_MISSING_FUNCTION_NAME,
  333. ERR_EXPECTED_OPEN_BRACKET,
  334. ERR_TO_MUCH_ARGUMENTS,
  335. ERR_EXPECTED_ARGUMENT_NAME,
  336. ERR_EXPECTED_CLOSE_BRACKET,
  337. ERR_EXPECTED_REGISTER_NAME,
  338. ERR_ILLEGAL_REGISTER,
  339. ERR_REGISTER_USED_TWICE,
  340. ERR_AGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER,
  341. ERR_ASSUMING_BIAS_OF_30,
  342. ERR_EXTRA_CHARACTERS,
  343. ERR_MISSING_BASENAME,
  344. ERR_WRITING_FILE,
  345. ERR_EXPECTED_COMMA,
  346. ERR_DIFFERENT_TO_PREVIOUS,
  347. ERR_UNKNOWN_VARIABLE_TYPE,
  348. ERR_UNKNOWN_ERROR,
  349. };
  350.  
  351. struct ErrField {
  352.   UBYTE  Type;    // 0 = Error, 1 = Warning
  353.   UBYTE  Skip;
  354.   STRPTR Error;
  355. } Errors[] = {
  356. 1, 1, "Tag function must have arguments.",
  357. 1, 1, "Cannot convert pragma name into tag name.",
  358. 1, 1, "Tag definition without preceding Pragma.",
  359. 1, 0, "Basename declared twice.",
  360. 1, 0, "Expected preceding _ in Basename.",
  361. 1, 1, "Expected Basename.",
  362. 1, 0, "Expected Bias value.",
  363. 1, 0, "Assuming positive bias value.",
  364. 1, 1, "Missing function name.",
  365. 1, 1, "Expected '('.",
  366. 1, 1, "Too much arguments.",
  367. 1, 1, "Expected argument name.",
  368. 1, 1, "Expected ')'.",
  369. 1, 1, "Expected register name.",
  370. 1, 1, "A5 and A6 not allowed as argument register.",
  371. 1, 1, "Register used twice.",
  372. 1, 0, "Number of arguments != number of registers.",
  373. 1, 0, "Assuming bias of 30.",
  374. 1, 1, "Extra characters.",
  375. 0, 0, "Missing Basename.",
  376. 0, 0, "Failed to write destination file.",
  377. 1, 1, "Expected ','.",
  378. 1, 1, "Data different to previous given.",
  379. 1, 0, "Unknown type \"%s\", no C++ name for %s.",
  380. 0, 0, "Unknown problem: program error or corrupt input data.",
  381. };
  382.  
  383. struct CPP_TypeField CPP_Field[] = {
  384. {"long",    4, 0,            CPP_TYPE_LONG},
  385. {"ULONG",    5, CPP_FLAG_UNSIGNED,    CPP_TYPE_LONG},
  386. {"LONGBITS",    8, CPP_FLAG_UNSIGNED,    CPP_TYPE_LONG},
  387. {"CPTR",    4, CPP_FLAG_UNSIGNED,    CPP_TYPE_LONG},
  388. {"Tag",        3, CPP_FLAG_UNSIGNED,    CPP_TYPE_LONG},
  389. {"Object",    6, CPP_FLAG_UNSIGNED,    CPP_TYPE_LONG},
  390. {"LONG",    4, 0,            CPP_TYPE_LONG},
  391. {"BPTR",    4, 0,            CPP_TYPE_LONG},
  392. {"BSTR",    4, 0,            CPP_TYPE_LONG},
  393. {"short",    5, 0,            CPP_TYPE_WORD},
  394. {"CxObj",    5, 0,            CPP_TYPE_LONG},
  395. {"CxMsg",    5, 0,            CPP_TYPE_LONG},
  396. {"USHORT",    6, CPP_FLAG_UNSIGNED,    CPP_TYPE_WORD},
  397. {"UWORD",    5, CPP_FLAG_UNSIGNED,    CPP_TYPE_WORD},
  398. {"UCOUNT",    6, CPP_FLAG_UNSIGNED,    CPP_TYPE_WORD},
  399. {"WORDBITS",    8, CPP_FLAG_UNSIGNED,    CPP_TYPE_WORD},
  400. {"RPTR",    4, CPP_FLAG_UNSIGNED,    CPP_TYPE_WORD},
  401. {"SHORT",    5, 0,            CPP_TYPE_WORD},
  402. {"COUNT",    5, 0,            CPP_TYPE_WORD},
  403. {"WORD",    4, 0,            CPP_TYPE_WORD},
  404. {"BOOL",    4, 0,            CPP_TYPE_WORD},
  405. {"char",    4, 0,            CPP_TYPE_BYTE},
  406. {"UBYTE",    5, CPP_FLAG_UNSIGNED,    CPP_TYPE_BYTE},
  407. {"TEXT",    4, CPP_FLAG_UNSIGNED,    CPP_TYPE_BYTE},
  408. {"BYTEBITS",    8, CPP_FLAG_UNSIGNED,    CPP_TYPE_BYTE},
  409. {"BYTE",    4, 0,            CPP_TYPE_BYTE},
  410. {"void",    4, 0,            CPP_TYPE_VOID},
  411. {"VOID",    4, 0,            CPP_TYPE_VOID},
  412. {"float",    5, 0,            CPP_TYPE_FLOAT},
  413. {"FLOAT",    5, 0,            CPP_TYPE_FLOAT},
  414. {"double",    6, 0,            CPP_TYPE_DOUBLE},
  415. {"DOUBLE",    6, 0,            CPP_TYPE_DOUBLE},
  416. {"STRPTR",    6, CPP_FLAG_POINTER|CPP_FLAG_STRPTR,    CPP_TYPE_BYTE},
  417. {"APTR",    4, CPP_FLAG_POINTER,    CPP_TYPE_VOID},
  418. {"ClassID",    7, CPP_FLAG_POINTER|CPP_FLAG_UNSIGNED,    CPP_TYPE_BYTE},
  419. {"PLANEPTR",    8, CPP_FLAG_POINTER|CPP_FLAG_UNSIGNED,    CPP_TYPE_BYTE},
  420. {"DisplayInfoHandle",17,CPP_FLAG_POINTER,CPP_TYPE_VOID},
  421. {0,0,0,0},
  422. };
  423.  
  424. void DoError(UBYTE errnum, ULONG line, ...)
  425. {
  426.   STRPTR *arguments = (STRPTR *) (((STRPTR) &line) + sizeof(ULONG));
  427.   struct {
  428.     STRPTR type;
  429.     ULONG typenum;
  430.     ULONG linenum;
  431.   } args;
  432.  
  433.   args.type = Errors[errnum].Type ? "Warning" : "Error";
  434.   args.typenum = errnum;
  435.   args.linenum = line;
  436.  
  437.   VPrintf((line ? "%s %ld in line %ld: " : "%s %ld : "), &args);
  438.   VPrintf(Errors[errnum].Error, arguments);
  439.   PutStr("\n");
  440.   if(line && Errors[errnum].Skip)
  441.   {
  442.     while(*in.pos)
  443.       ++in.pos;
  444.   }
  445. }
  446.  
  447. ULONG Out(ULONG size)
  448. {
  449.   ULONG i = out.pos-out.buf;
  450.  
  451.   if(i && out.size - i <= size)
  452.   {
  453.     if(Write(out.file, out.buf, i) != i)
  454.     {
  455.       Output_Error = 0;
  456.       return 0;
  457.     }
  458.     out.count += i;
  459.     out.pos = out.buf;
  460.   }
  461.   return out.size;
  462. }
  463.  
  464. #ifdef __MAXON__
  465.   #define __asm
  466.   #define __saveds
  467.   #include <linkerfunc.h>
  468. #endif
  469.  
  470. static void __asm __saveds putfunc(register __d0 UBYTE data,
  471. register __a3 LONG *a)
  472. {
  473. #ifdef __MAXON__
  474.   GetBaseReg();
  475. #endif
  476.  
  477.   if(data)
  478.   {
  479.     if(!*a)
  480.       *a = Out(1);
  481.     if((*a)-- > 0)
  482.       *(out.pos++) = data;
  483.   }
  484. }
  485.  
  486. typedef void (*putchtype) ();
  487.  
  488. ULONG DoOutput(STRPTR format, ...)
  489. {
  490.   LONG a = out.buf+out.size-out.pos;
  491.  
  492.   if(!Output_Error)
  493.     return 0;
  494.  
  495.   RawDoFmt(format, (APTR) ((ULONG)&format+sizeof(STRPTR)),
  496.   (putchtype) putfunc, &a);
  497.  
  498.   if(a < 0)
  499.     return 0;
  500.   return 1;
  501. }
  502.  
  503. ULONG DoOutputDirect(APTR data, ULONG size)
  504. {
  505.   if(!Output_Error || !Out(size))
  506.     return 0;
  507.   CopyMem(data, out.pos, size);
  508.   out.pos += size;
  509.   return 1;
  510. }
  511.  
  512. STRPTR SkipBlanks(STRPTR OldPtr)
  513. {
  514.   while(*OldPtr == ' ' || *OldPtr == '\t')
  515.     ++OldPtr;
  516.   return OldPtr;
  517. }
  518.  
  519. /*
  520.     This function is used to skip over variable names.
  521.  
  522.     Inputs: OldPtr  - pointer to the beginning of a string.
  523.  
  524.     Result: Pointer to the first character of the string, that is not one
  525.         of a-z, A-Z, 0-9 or the underscore.
  526. */
  527.  
  528. STRPTR SkipName(STRPTR OldPtr)
  529. {
  530.   while(isalnum(*OldPtr) || *OldPtr == '_')
  531.     ++OldPtr;
  532.   return OldPtr;
  533. }
  534.  
  535. ULONG MakeTagFunction(struct AmiPragma *ap)
  536. {
  537.   ULONG len = strlen(ap->FuncName);
  538.  
  539. #ifdef DEBUG_OLD
  540.   VPrintf("MakeTagFunction:\n", 0);
  541. #endif
  542.  
  543.   ++tagfuncs;
  544.  
  545.   if(!strcmp(ap->FuncName, "VFWritef") ||
  546.   !strcmp(ap->FuncName, "VFPrintf") ||
  547.   !strcmp(ap->FuncName, "VPrintf"))
  548.   {
  549.     if(!(ap->TagName = strndup(ap->FuncName+1, len-1)))
  550.       return 0;
  551.   }
  552.   else if(ap->FuncName[len-1] == 'A')
  553.   {
  554.     if(!strcmp(ap->FuncName+len-3, "DMA"))
  555.     { --tagfuncs; return 1;}
  556.     if(!(ap->TagName = strndup(ap->FuncName, len-1)))
  557.       return 0;
  558.   }
  559.   else if(!strcmp(ap->FuncName + len-7, "TagList"))
  560.   {
  561.     if(!(ap->TagName = strndup(ap->FuncName, len-3)))
  562.       return 0;
  563.     ap->TagName[len-4] = 's';
  564.   }
  565.   else if(!strcmp(ap->FuncName + len-4, "Args"))
  566.   {
  567.     if(!strcmp(ap->FuncName, "ReadArgs") || !strcmp(ap->FuncName, "FreeArgs"))
  568.     { --tagfuncs;  return 1;}
  569.     if(!(ap->TagName = strndup(ap->FuncName, len-4)))
  570.       return 0;
  571.   }
  572.   else if(!stricmp(ap->Args[ap->NumArgs-1].ArgName, "tags") ||
  573.   !stricmp(ap->Args[ap->NumArgs-1].ArgName, "taglist"))
  574.   {
  575.     if(!(ap->TagName = strndup(ap->FuncName, len+4)))
  576.       return 0;
  577.     CopyMem("Tags", ap->TagName + len, 5);
  578.   }
  579.   else if(!stricmp(ap->Args[ap->NumArgs-1].ArgName, "args"))
  580.   {
  581.     if(!(ap->TagName = strndup(ap->FuncName, len+4)))
  582.       return 0;
  583.     CopyMem("Args", ap->TagName + len, 5);
  584.   }
  585.   else
  586.     --tagfuncs; /* not a tagfunction, incrementing was false, undo it */
  587.  
  588.   return 1;
  589. }
  590.  
  591. void MakeLines(STRPTR buffer, ULONG size, ULONG test)
  592. {
  593.   ULONG a = 0;
  594.   if(size && buffer)
  595.   {
  596.     // make a real C++ zero string ending line
  597.     while(--size)
  598.     {
  599.       switch(*buffer)
  600.       {
  601.       case '(': ++a; break;
  602.       case ')': --a; break;
  603.       case '\n':
  604.         if(!test || !a)
  605.           *buffer = '\0';
  606.         else
  607.           *buffer = ' ';
  608.         break;
  609.       }
  610.       ++buffer;
  611.     }
  612.     *buffer = '\0';
  613.   }
  614. }
  615.  
  616. ULONG ScanFDFile(void)
  617. {
  618. #ifdef DEBUG_OLD
  619.   VPrintf("ScanFDFile:\n", 0);
  620. #endif
  621.  
  622.   ULONG _public = 1;
  623.   LONG bias = -1;
  624.   ULONG linenum, len;
  625.   ULONG actcom = 0;
  626.  
  627.   for(linenum = 1; !CTRL_C && in.pos < in.buf + in.size; ++linenum)
  628.   {
  629.     if(*in.pos == '*')       /*  Comment   */
  630.     {
  631.       STRPTR oldpos = in.pos;
  632. #ifdef DEBUG_OLD
  633.   VPrintf("ScanFDFile: found a comment\n", 0);
  634. #endif
  635.       in.pos = SkipBlanks(in.pos+1);
  636.       if(!strnicmp(in.pos, "tagcall", 7))  /*  Tag to create?  */
  637.       {
  638.         struct AmiPragma *prevpragma = (struct AmiPragma *)
  639.         AmiPragma.Last;
  640.  
  641.     in.pos = SkipBlanks(in.pos + 7);
  642.     if(!prevpragma)
  643.     {
  644.       DoError(ERR_TAG_DEF_WITHOUT_PRAGMA, linenum);
  645.       ++in.pos;
  646.       continue;
  647.     }
  648.  
  649.     if(!prevpragma->NumArgs)
  650.     {
  651.       DoError(ERR_TAGFUNC_NEEDS_ARGUMENT, linenum);
  652.       ++in.pos;
  653.           continue;
  654.     }
  655.  
  656.     // Get the tag functions name.
  657.  
  658.         if(!prevpragma->TagName)
  659.           ++tagfuncs;
  660.  
  661.     if(*in.pos)
  662.     {
  663.       STRPTR oldptr, tptr = prevpragma->TagName;
  664.  
  665.       len = strlen(prevpragma->FuncName)+strlen(in.pos)+1;
  666.       if(!(prevpragma->TagName = strndup(prevpragma->FuncName, len)))
  667.         return 0;
  668.  
  669.       if(*in.pos == '-')
  670.       {
  671.             STRPTR removeptr;
  672.  
  673.         oldptr = in.pos = SkipBlanks(in.pos+1);
  674.         in.pos = SkipName(in.pos);
  675.         if((len = in.pos-oldptr))
  676.         {
  677.               removeptr = prevpragma->TagName+strlen(prevpragma->TagName)-len;
  678.           if(strncmp(removeptr, oldptr, len))
  679.           {
  680. #ifdef DEBUG
  681.         {
  682.           struct data {STRPTR a;STRPTR b;ULONG c;} a;
  683.           a.a = removeptr;
  684.           a.b = oldptr;
  685.           a.c = len;
  686.           VPrintf("ScanFDFile: *tagcall -: %s, %s, %ld\n", &a);
  687.         }
  688. #endif
  689.         DoError(ERR_CANNOT_CONVERT_PRAGMA_TAGCALL, linenum);
  690.         prevpragma->TagName = tptr;
  691.         ++in.pos;
  692.                 continue;
  693.           }
  694.  
  695.           *removeptr = '\0';
  696.         }
  697.         in.pos = SkipBlanks(in.pos);
  698.       }
  699.       if(*in.pos == '+')
  700.             in.pos = SkipBlanks(in.pos+1);
  701.  
  702.       in.pos = SkipName((oldptr = in.pos));
  703.       len = in.pos-oldptr;
  704.       if(len)
  705.       {
  706.             ULONG a = strlen(prevpragma->TagName);
  707.             CopyMem(oldptr, prevpragma->TagName+a, len);
  708.             prevpragma->TagName[a+len] = '\0';
  709.       }
  710.     }
  711.         else if(!prevpragma->TagName)
  712.         {
  713.       len = strlen(prevpragma->FuncName);
  714.           if(!(prevpragma->TagName = strndup(prevpragma->FuncName, len+4)))
  715.             return 0;
  716.           CopyMem("Tags", prevpragma->TagName + len, 5);
  717.         }
  718.       }
  719.       else
  720.       {
  721.     if(actcom)
  722.       *(oldpos-1) = '\n';
  723.     else if(Flags & FLAG_DOCOMMENT)
  724.     {
  725.           struct Comment *d;
  726.           if(!(d = (struct Comment *) NewItem(&Comment)))
  727.             return 0;
  728.       d->Bias = bias;
  729.       d->Data = oldpos;
  730.       AddItem(&Comment, (struct ShortList *) d);
  731.       actcom = 1;
  732.     }
  733.         while(*in.pos)
  734.           ++in.pos;
  735.       }
  736.     }
  737.     else if(!strnicmp(in.pos, "##base", 6))
  738.     {
  739. #ifdef DEBUG_OLD
  740.   VPrintf("ScanFDFile: found ##base\n", 0);
  741. #endif
  742.       STRPTR oldptr;
  743.  
  744.       actcom = 0; // kein Comment
  745.  
  746.       if(BaseName)
  747.         DoError(ERR_BASENAME_DECLARED_TWICE, linenum);
  748.  
  749.       in.pos = SkipBlanks(in.pos+6);
  750.       if(*in.pos != '_')
  751.     DoError(ERR_EXPECTED_SLASH_IN_BASENAME, linenum);
  752.       else
  753.         ++in.pos;
  754.  
  755.       in.pos = SkipName((oldptr = in.pos));
  756.       if((len = in.pos-oldptr))
  757.       {
  758.         if(!(BaseName = strndup(oldptr, len)))
  759.           return 0;
  760.     if(!ShortBaseName && !(ShortBaseName = strndup(BaseName, len-4)))
  761.           return 0;
  762.  
  763.         if(!(ShortBaseNameUpper = strndup(ShortBaseName, strlen(ShortBaseName))))
  764.           return 0;
  765.     else
  766.         {
  767.           STRPTR a = ShortBaseNameUpper;
  768.           while((*a = toupper(*a))) // Convert to uppercase
  769.             a++;
  770.         }
  771.       }
  772.       else
  773.     DoError(ERR_EXPECTED_BASENAME, linenum);
  774.     }
  775.     else if(!strnicmp(in.pos, "##bias", 6))
  776.     {
  777. #ifdef DEBUG_OLD
  778.   VPrintf("ScanFDFile: found ##bias\n", 0);
  779. #endif
  780.       STRPTR ptr;
  781.       LONG newbias;
  782.  
  783.       actcom = 0;
  784.  
  785.       in.pos += 7;
  786.       newbias = strtol(in.pos, &ptr, 10);
  787.       if(ptr == in.pos)
  788.     DoError(ERR_EXPECTED_BIAS_VALUE, linenum);
  789.       else if(newbias < 0)
  790.       {
  791.     DoError(ERR_ASSUMING_POSITIVE_BIAS_VALUE, linenum);
  792.     bias = -newbias;
  793.       }
  794.       else
  795.     bias = newbias;
  796.       in.pos = SkipName(in.pos);
  797.     }
  798.     else if(!strnicmp(in.pos, "##end", 5))
  799.       break;
  800.     else if(!strnicmp(in.pos, "##shadow", 8)) /* introduced by Storm */
  801.     {
  802.       actcom = 0;
  803.       in.pos += 8;
  804.       bias -= 6;
  805.     }
  806.     else if(!strnicmp(in.pos, "##public", 8))
  807.     {
  808.       actcom = 0;
  809.       in.pos += 8;
  810.       _public = 1;
  811.     }
  812.     else if(!strnicmp(in.pos, "##private", 9))
  813.     {
  814.       actcom = 0;
  815.       in.pos += 9;
  816.       _public = 0;
  817.     }
  818.     else
  819.     {
  820. #ifdef DEBUG_OLD
  821.   VPrintf("ScanFDFile: scan Function\n", 0);
  822. #endif
  823.       STRPTR oldptr;
  824.       struct AmiPragma ap;
  825.       ULONG numargs;
  826.  
  827.       memset(&ap, 0, sizeof(struct AmiPragma));
  828.       actcom = 0;
  829.  
  830.       oldptr = in.pos = SkipBlanks(in.pos);
  831.       in.pos = SkipName(oldptr);
  832.       if(!(len = in.pos-oldptr))
  833.       {
  834.     DoError(ERR_MISSING_FUNCTION_NAME, linenum);
  835.     ++in.pos;
  836.     continue;
  837.       }
  838.  
  839.       ap.FuncName = oldptr;
  840.  
  841.       in.pos = SkipBlanks(in.pos);
  842.       if(*in.pos != '(')
  843.       {
  844.     DoError(ERR_EXPECTED_OPEN_BRACKET, linenum);
  845.     ++in.pos;
  846.     continue;
  847.       }
  848.  
  849.       *in.pos = '\0'; // create c string of FunctionName
  850.  
  851. #ifdef DEBUG_OLD
  852.   VPrintf("ScanFDFile: found function %s\n", &ap.FuncName);
  853. #endif
  854.  
  855.       do
  856.       {
  857.         oldptr = in.pos = SkipBlanks(in.pos+1);
  858.  
  859.     if(*in.pos == ')' && !ap.NumArgs)
  860.       break;
  861.  
  862.     if(ap.NumArgs == 14)
  863.         {
  864.       DoError(ERR_TO_MUCH_ARGUMENTS, linenum); break;
  865.         }
  866.  
  867.     in.pos = SkipName(oldptr);
  868.         if(*in.pos == '*')
  869.           ++in.pos;
  870.     if(!(len = in.pos-oldptr))
  871.     {
  872.       DoError(ERR_EXPECTED_ARGUMENT_NAME, linenum);
  873.       break;
  874.     }
  875.  
  876.     ap.Args[ap.NumArgs++].ArgName = oldptr;
  877.     oldptr = in.pos;
  878.  
  879.     in.pos = SkipBlanks(in.pos);
  880.     if(*in.pos != ',' && *in.pos != '/' && *in.pos != ')')
  881.     {
  882.       DoError(ERR_EXPECTED_CLOSE_BRACKET, linenum);
  883.       break;
  884.     }
  885.     if(*in.pos != ')') // create c string ending
  886.       *oldptr = '\0';
  887.       }
  888.       while(*in.pos != ')');
  889.       if(*in.pos != ')')
  890.       {
  891.         while(*(in.pos++))
  892.           ++in.pos;
  893.         continue;
  894.       }
  895.       else
  896.         *oldptr = '\0';    // create c string ending for last argument
  897.     
  898.       if(*(in.pos = SkipBlanks(in.pos+1)) != '(')
  899.       {
  900.         DoError(ERR_EXPECTED_OPEN_BRACKET, linenum);
  901.     ++in.pos;
  902.     continue;
  903.       }
  904.  
  905.       numargs = 0;
  906.       do
  907.       {
  908.         ULONG i;
  909.  
  910.     oldptr = in.pos = SkipBlanks(in.pos + 1);
  911.  
  912.     if(*in.pos == ')' && numargs == 0)
  913.       break;
  914.  
  915.     in.pos = SkipName(oldptr);
  916.     len = in.pos-oldptr;
  917.  
  918.     for(i = 0; i < 16; i++)
  919.           if(!strnicmp(&RegNames[i<<2], oldptr, len))
  920.         break;
  921.  
  922.     if(i == 16)
  923.     {
  924.       DoError(ERR_EXPECTED_REGISTER_NAME, linenum);
  925.       break;
  926.     }
  927.     if(i > 14)
  928.     {
  929.       DoError(ERR_ILLEGAL_REGISTER, linenum);
  930.       break;
  931.     }
  932.  
  933.     ap.Args[numargs].ArgReg = i;
  934.  
  935.     for(i = 0; i < numargs; i++)
  936.     {
  937.           if(ap.Args[numargs].ArgReg == ap.Args[i].ArgReg)
  938.       {
  939.         DoError(ERR_REGISTER_USED_TWICE, linenum);
  940.         break;
  941.       }
  942.     }
  943.         if(i < numargs)
  944.           break;
  945.  
  946.     ++numargs;
  947.  
  948.     in.pos = SkipBlanks(in.pos);
  949.     if(*in.pos != ',' && *in.pos != '/' && *in.pos != ')')
  950.     {
  951.       DoError(ERR_EXPECTED_CLOSE_BRACKET, linenum);
  952.       break;
  953.     }
  954.       }
  955.       while(*in.pos != ')');
  956.       if(*in.pos != ')')
  957.       {
  958.         while(*(in.pos++))
  959.           ++in.pos;
  960.         continue;
  961.       }
  962.       else
  963.         ++in.pos;
  964.  
  965.       if(Flags & FLAG_STORMFD)
  966.       {
  967.         if(!strcmp(ap.Args[ap.NumArgs-1].ArgName, "tags"))
  968.      {
  969.       ap.TagName = ap.FuncName;
  970.       ap.FuncName = 0;
  971.       ++tagfuncs;
  972. #ifdef DEBUG
  973.           VPrintf("ScanFDFile: StormFD mode, tag func: %s\n", &ap.TagName);
  974. #endif
  975.     }
  976. #ifdef DEBUG
  977.     else
  978.     {
  979.       STRPTR a[2];
  980.       a[0] = ap.FuncName;
  981.       a[1] = ap.Args[ap.NumArgs-1].ArgName;
  982.           VPrintf("ScanFDFile: StormFD mode, normal func: %s(..., %s)\n", &a);
  983.     }
  984. #endif
  985.       }
  986.       else if(!MakeTagFunction(&ap))
  987.         return 0;
  988.  
  989.       if(numargs != ap.NumArgs)
  990.       {
  991.     DoError(ERR_AGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER, linenum);
  992.         ap.NumArgs = numargs;
  993.       }
  994.  
  995.       if(bias == -1)
  996.       {
  997.     DoError(ERR_ASSUMING_BIAS_OF_30, linenum);
  998.     bias = 30;
  999.       }
  1000.       ap.Bias = bias;
  1001.       bias += 6;
  1002.  
  1003.       ap.Public = _public;
  1004.  
  1005.       {
  1006.     struct AmiPragma *d;
  1007.         if(!(d = (struct AmiPragma *) NewItem(&AmiPragma)))
  1008.           return 0;
  1009.         CopyMem(&ap, d, sizeof(struct AmiPragma));
  1010.         AddItem(&AmiPragma, (struct ShortList *) d);
  1011.       }
  1012.     }
  1013.  
  1014.     in.pos = SkipBlanks(in.pos);
  1015.     if(*in.pos)
  1016.       DoError(ERR_EXTRA_CHARACTERS, linenum);
  1017.     ++in.pos; // skip '\0'
  1018.   }
  1019.  
  1020.   if(CTRL_C)
  1021.     return 0;
  1022.  
  1023.   if(!BaseName)
  1024.   {
  1025.     DoError(ERR_MISSING_BASENAME, 0); return 0;
  1026.   }
  1027.  
  1028.   return 1;
  1029. }
  1030.  
  1031. void FindHeader(void)
  1032. {
  1033.   STRPTR str = HEADER;
  1034.   ULONG mode = 0;
  1035.  
  1036.   do
  1037.   {
  1038.     if(!mode)
  1039.       HEADER = str;
  1040.  
  1041.     if(*str == '/')
  1042.     {
  1043.       ++str;
  1044.       if(*str == '*')
  1045.       {
  1046.     mode = 2; break;
  1047.       }
  1048.       else if(*str == '/')
  1049.     mode = 1;
  1050.     }
  1051.     else if(*str == '*' || *str == ';')
  1052.       mode = 1;
  1053.     else if(mode)
  1054.       break;
  1055.     while(*str && *(str++) != '\n')
  1056.       ;
  1057.   } while(*str);
  1058.  
  1059.   if(mode == 2)
  1060.   {
  1061.     while(*str && (*(str-1) != '*' || *str != '/'))
  1062.       ++str;
  1063.     while(*str && *(str++) != '\n')
  1064.       ;
  1065.   }
  1066.    
  1067.   if(mode)
  1068.     headersize = str-HEADER;
  1069.   else
  1070.   {
  1071.     HEADER = 0; headersize = 0;
  1072.   }
  1073. }
  1074.  
  1075. /* returns decrement data in bits 0-15 and increment data in bits 16-31 */
  1076. ULONG GetRegisterData(struct AmiPragma *ap)
  1077. {
  1078. /* usage of result:
  1079.     48E7 <lower word>    MOVEM.L <registers>,-(A7) ; D0 is bit 15
  1080.     4CDF <upper word>    MOVEM.L (A7)+,<registers> ; D0 is bit 0
  1081. */
  1082.   register ULONG i, data = 0, reg;
  1083.  
  1084.   for(i = 0; i < ap->NumArgs; ++i)
  1085.   {
  1086.     reg = ap->Args[i].ArgReg;
  1087.  
  1088.     if(reg >= 10 || (reg >= 2 &&  reg <= 7)) /* A2-A7 and D2-D7 */
  1089.       data |= (1 << (reg + 16)) + (1 << (15 - reg));
  1090.   }
  1091.   if(data)    /* set A6 only when other register used */
  1092.     data |= 0x40000002;
  1093.   return data;
  1094. }
  1095.  
  1096. static void __asm __saveds xdefputfunc(register __d0 UBYTE data,
  1097. register __a3 STRPTR *a)
  1098. {
  1099.   *((*a)++) = data;
  1100. }
  1101.  
  1102. ULONG OutputXDEF(STRPTR format, ...)
  1103. {
  1104.   UBYTE b[150];
  1105.   STRPTR c = b + 4;
  1106.   UWORD i;
  1107.  
  1108.   memset(b, 0, 150);
  1109.   RawDoFmt(format, (APTR) ((ULONG)&format+sizeof(STRPTR)),
  1110.   (putchtype) xdefputfunc, &c);
  1111.   // c now holds pointer to end
  1112.   i = (c-(b+4)+2)>>2;
  1113.   *((ULONG *) b) = 0x01000000 + i;
  1114.  
  1115.   return DoOutputDirect(b, (i+2)<<2);
  1116. }
  1117.  
  1118. /* ------------------------------------------------------------------ */
  1119.  
  1120. struct ShortList *NewItem(struct ShortListRoot *list)
  1121. {
  1122.   struct ShortList *item;
  1123.   if(!list || !list->Size)
  1124.     return 0;
  1125.   if(!(item = (struct ShortList *) AllocRemember(&remember, list->Size,
  1126.   MEMF_ANY|MEMF_CLEAR)))
  1127.     return 0;
  1128.   return item;
  1129. }
  1130.  
  1131. struct ShortList *RemoveItem(struct ShortListRoot *list, struct ShortList *item)
  1132. {
  1133.   struct ShortList *n = list->First;
  1134.  
  1135.   if(n == item)
  1136.     list->First = item->Next;
  1137.   else
  1138.   {
  1139.     while(n && n->Next != item)
  1140.       n = n->Next;
  1141.     if(!n)
  1142.       return 0;
  1143.     if(!(n->Next = item->Next))
  1144.       list->Last = n;
  1145.   }
  1146.   item->Next = 0;
  1147.   return item;
  1148. }
  1149.  
  1150. void AddItem(struct ShortListRoot *list, struct ShortList *item)
  1151. {
  1152.   if(!list->First)
  1153.     list->First = list->Last = item;
  1154.   else
  1155.   {
  1156.     list->Last->Next = item;
  1157.     list->Last = item;
  1158.   }
  1159. }
  1160.  
  1161. /* ------------------------------------------------------------------ */
  1162.  
  1163. ULONG FuncAMICALL(struct AmiPragma *Ap, ULONG tagmode)
  1164. {
  1165.   ULONG i;
  1166.  
  1167.   DoOutput("#pragma %s(%s,0x%03lx,%s("/*))*/, tagmode ? "tagcall" :
  1168.   "amicall", BaseName, Ap->Bias, tagmode ? Ap->TagName : Ap->FuncName);
  1169.  
  1170.   for(i = 0; i < Ap->NumArgs; ++i)
  1171.   {
  1172.     DoOutput(&RegNames[(Ap->Args[i].ArgReg)<<2]);
  1173.     if(i+1 < Ap->NumArgs)
  1174.       DoOutput(",");
  1175.   }
  1176.  
  1177.   return DoOutput(/*((*/"))\n");
  1178. }
  1179.  
  1180. ULONG FuncLIBCALL(struct AmiPragma *Ap, ULONG tagmode)
  1181. {
  1182.   LONG i;
  1183.  
  1184.   if((Flags & FLAG_SYSCALL) && !strcmp(BaseName,"SysBase"))
  1185.     DoOutput("#pragma syscall %-20s %03lx ", Ap->FuncName, Ap->Bias);
  1186.   else
  1187.     DoOutput("#pragma %s %s %-20s %03lx ", tagmode ? "tagcall" :
  1188.     "libcall", BaseName, tagmode ? Ap->TagName : Ap->FuncName, Ap->Bias);
  1189.  
  1190.   for(i = Ap->NumArgs-1; i >= 0; --i)
  1191.     DoOutput("%lx",Ap->Args[i].ArgReg);
  1192.  
  1193.   return DoOutput("0%lx\n", Ap->NumArgs);
  1194. }
  1195.  
  1196. ULONG FuncAsmText(struct AmiPragma *ap, ULONG tagmode)
  1197. {
  1198.   STRPTR text = tagmode ? ap->TagName : ap->FuncName, a;
  1199.   LONG i;
  1200.   ULONG registers;
  1201.   ULONG offset = 1;
  1202.  
  1203.   DoOutput("\n\tXDEF\t_%s\n_%s:\n",text, text);
  1204.   if(!ap->NumArgs && clibbuf)
  1205.     DoOutput("\tXDEF\t%s_\n%s_:\n",text, text);
  1206.   else if((a = FindClibFunc(text)))
  1207.   {
  1208.     UBYTE name[300];
  1209.     ULONG ret = 0;
  1210.  
  1211.     do
  1212.     {
  1213.       if((ret = CopyCPPType(name, a, ret, text, ap->Args)))
  1214.         DoOutput("\tXDEF\t%s__%s\n%s__%s:\n",text, name, text, name);
  1215.     } while(ret == 0xFFFFFFFF);
  1216.   }
  1217.  
  1218.   if((registers = GetRegisterData(ap) >> 16))
  1219.   {
  1220.     UWORD l = registers;
  1221.  
  1222.     DoOutput("\tMOVEM.L\t");
  1223.  
  1224.     for(i = 0; i <= 15; ++i)
  1225.     {
  1226.       if(l & (1 << i))
  1227.       {
  1228.     ++offset;
  1229.         l ^= 1 << i;
  1230.     DoOutput(&RegNames[i<<2]);
  1231.     if(l)
  1232.       DoOutput("/");
  1233.       }
  1234.     }
  1235.     DoOutput(",-(A7)\n");
  1236.   }
  1237.   else
  1238.   {
  1239.     DoOutput("\tMOVE.L\tA6,-(A7)\n"); ++offset;
  1240.   }
  1241.  
  1242.   DoOutput("\tMOVE.L\t_%s,A6\n", BaseName);
  1243.  
  1244.   for(i = 0; i < ap->NumArgs - (tagmode ? 1 : 0); ++i)
  1245.     DoOutput("\tMOVE.L\t%02ld(A7),%s\n", (i+offset)<<2,
  1246.     &RegNames[(ap->Args[i].ArgReg)<<2]);
  1247.  
  1248.   if(i < ap->NumArgs)
  1249.   {
  1250.     if(ap->Args[i].ArgReg > 7)
  1251.       DoOutput("\tLEA\t%02ld(A7),%s\n", (i+offset)<<2,
  1252.       &RegNames[(ap->Args[i].ArgReg)<<2]);
  1253.     else
  1254.       DoOutput("\tMOVE.L\tA7,%s\n\tADD%s.L\t#%02ld,%s\n",
  1255.       &RegNames[(ap->Args[i].ArgReg)<<2], (i + offset <= 2 ? "Q" : ""),
  1256.       (i+offset)<<2, &RegNames[(ap->Args[i].ArgReg)<<2]);
  1257.   }
  1258.  
  1259.   DoOutput("\tJSR\t-%03ld(A6)\n",ap->Bias);
  1260.  
  1261.   if(registers)
  1262.   {
  1263.     DoOutput("\tMOVEM.L\t(A7)+,");
  1264.  
  1265.     for(i = 0; i <= 15; ++i)
  1266.     {
  1267.       if(registers & (1 << i))
  1268.       {
  1269.         registers ^= 1 << i;
  1270.     DoOutput(&RegNames[i<<2]);
  1271.     if(registers)
  1272.       DoOutput("/");
  1273.       }
  1274.     }
  1275.     DoOutput("\n");
  1276.   }
  1277.   else
  1278.     DoOutput("\tMOVE.L\t(A7)+,A6\n");
  1279.  
  1280.   return DoOutput("\tRTS\n");
  1281. }
  1282.  
  1283. ULONG FuncAsmCode(struct AmiPragma *ap, ULONG tagmode)
  1284. {
  1285.   ULONG registers;
  1286.   STRPTR text = tagmode ? ap->TagName : ap->FuncName, str;
  1287.   ULONG a[5];
  1288.   ULONG offset = 1;
  1289.   LONG i = strlen(ShortBaseNameUpper);
  1290.  
  1291.   registers = GetRegisterData(ap);
  1292.  
  1293.   a[0] = HUNK_UNIT; a[1] = 0; a[2] = HUNK_NAME;
  1294.   a[3] = (i + 6 + 3)>>2;
  1295.  
  1296.   DoOutputDirect(a, 16);
  1297.   DoOutputDirect(ShortBaseNameUpper, i);
  1298.   DoOutputDirect("_STUBS\0\0\0", (a[3]<<2)-i);
  1299.  
  1300.   a[0] = HUNK_CODE; a[1] = ap->NumArgs + (registers ? 5 : 4);
  1301.  
  1302.   if(tagmode && ap->NumArgs > 1 && ap->Args[ap->NumArgs-1].ArgReg <= 7)
  1303.     ++a[1];    /* one longword more, when D register and tagcall */
  1304.  
  1305.   DoOutputDirect(a, 8);
  1306.  
  1307.   a[0] = 0x2F0E2C79, a[1] = 0;
  1308.  
  1309.   if(registers)
  1310.   {
  1311.     UWORD l = 0x48E7;
  1312.     a[0] = (registers << 16) + 0x2C79;
  1313.     DoOutputDirect(&l, 2);
  1314.     for(l = (UWORD) registers; l; l >>= 1)
  1315.     {
  1316.       if(l & 1)
  1317.         ++offset;
  1318.     }
  1319.   }
  1320.   else
  1321.     ++offset;
  1322.  
  1323.   DoOutputDirect(a, 8);
  1324.  
  1325.   for(i = 0; i < ap->NumArgs - (tagmode ? 1 : 0); ++i) // MOVE.L code generieren
  1326.   {
  1327.     ULONG j;
  1328.  
  1329.     a[0] = 0x202F0000 + ((i+offset)<<2);
  1330.  
  1331.     j = ap->Args[i].ArgReg;
  1332.     if(j > 7)
  1333.     {
  1334.       a[0] |= 0x400000; j -= 8;    // set MOVEA bit
  1335.     }
  1336.     a[0] |= j << 25;        // set destination register
  1337.  
  1338.     DoOutputDirect(a, 4);
  1339.   }
  1340.  
  1341.   if(i < ap->NumArgs)
  1342.   {
  1343.     ULONG j = ap->Args[i].ArgReg;
  1344.     if(j > 7)
  1345.     {                // LEA x(A7),Ax
  1346.       a[0] = (0x41EF0000 | ((j-8) << 25)) + ((i+offset) << 2);
  1347.     }
  1348.     else if(i+offset == 2)
  1349.     {                // MOVE.L A7,Dx  -- ADDQ.L #8,Dx
  1350.       a[0] = 0x200F5080 | j | (j << 25);
  1351.     }
  1352.     else
  1353.     {                // MOVE.L A7,Dx  -- ADD.L #x,Dx
  1354.       a[0] = 0x200FD0BC | (j << 25) | (j<<9);
  1355.       a[1] = (i+offset) << 2;
  1356.     }
  1357.  
  1358.     DoOutputDirect(a, (i + offset != 2 && j <= 7) ? 8 : 4);
  1359.   }
  1360.  
  1361.   // here comes the base reference
  1362.   a[0] = 0x4EAE0000 + (UWORD) (- ap->Bias); //JSR instruction
  1363.  
  1364.   DoOutputDirect(a, 4);
  1365.  
  1366.   if(registers)
  1367.   {
  1368.     a[0] = 0x4CDF0000 + (registers >> 16);
  1369.     a[1] = 0x4E750000;
  1370.     DoOutputDirect(a, 6);
  1371.   }
  1372.   else
  1373.   {
  1374.     a[0] = 0x2C5F4E75;
  1375.     DoOutputDirect(a, 4);
  1376.   }
  1377.  
  1378.   a[0] = HUNK_EXT;
  1379.   a[1] = 0x81000000 + ((strlen(BaseName) + 1 + 3)>>2);
  1380.   a[2] = 0x5F000000;
  1381.  
  1382.   DoOutputDirect(a, 9);
  1383.   DoOutputDirect(BaseName, (((UWORD) a[1])<<2)-1);
  1384.  
  1385.   a[0] = 1; a[1] = (registers ? 6 : 4);
  1386.   DoOutputDirect(a, 8);
  1387.  
  1388.   // here come the XDEF name references
  1389.   OutputXDEF("%s", text);        // Asm name
  1390.   OutputXDEF("_%s", text);        // C name
  1391.  
  1392.   if(!ap->NumArgs && clibbuf)
  1393.     OutputXDEF("%s_", text);        // C++ name no parameters
  1394.   else if((str = FindClibFunc(text)))
  1395.   {
  1396.     UBYTE name[100];
  1397.     ULONG ret = 0;
  1398.  
  1399.     do
  1400.     {
  1401.       if((ret = CopyCPPType(name, str, ret, text, ap->Args)))
  1402.     OutputXDEF("%s__%s", text, name); // C++ name with parameters
  1403.     } while(ret == 0xFFFFFFFF);
  1404.   }
  1405.  
  1406.   a[0] = 0; a[1] = HUNK_END;
  1407.  
  1408.   return DoOutputDirect(a, 8);
  1409. }
  1410.  
  1411. ULONG FuncCSTUBS(struct AmiPragma *ap, ULONG TagCall)
  1412. {
  1413.   STRPTR string,str2,lastarg;
  1414.   STRPTR ret = "return ";
  1415.   ULONG i;
  1416.  
  1417.   str2 = FindClibFunc(ap->TagName);
  1418.   if(!(string = FindClibFunc(ap->FuncName)))
  1419.     string = deftype;
  1420.  
  1421.   string = SkipBlanks(string);
  1422.   if(!strnicmp("void", string, 4))
  1423.     ret = 0;
  1424.  
  1425.   if(!OutClibType(string) || !DoOutput(" %s("/*)*/, ap->TagName))
  1426.     return 0;
  1427.   for(i = 0; i < ap->NumArgs-1; i++)
  1428.   {
  1429.     str2 = GetClibType(str2); // skip the equal parts
  1430.     if(!(string = GetClibType(string)) || !OutClibType(string) ||
  1431.     !DoOutput(" %s, ", ap->Args[i].ArgName))
  1432.       return 0;
  1433.   }
  1434.   lastarg = string;
  1435.   if((str2 = GetClibType(str2)))
  1436.   {
  1437.     if(!strncmp("...", str2, 3))
  1438.       str2 = 0;
  1439.     else if(!OutClibType(str2) || !DoOutput(" %s, ", ap->Args[i].ArgName))
  1440.       return 0;
  1441.   }
  1442.   else if(ap->NumArgs == 1 && !DoOutput("ULONG tag, "))
  1443.     return 0;
  1444.  
  1445.   if(!DoOutput(/*(*/"...)\n{\n  %s%s("/*)*/, ret, ap->FuncName))
  1446.     return 0;
  1447.   for(i = 0; i < ap->NumArgs-1; i++)
  1448.   {
  1449.     if(!DoOutput("%s, ", ap->Args[i].ArgName))
  1450.       return 0;
  1451.   }
  1452.   if(!DoOutput("("/*)*/) || !(string = GetClibType(string)) ||
  1453.   !OutClibType(string))
  1454.     return 0;
  1455.   if(str2)
  1456.   {
  1457.     if(!DoOutput(/*((*/") &%s);\n}\n", ap->Args[ap->NumArgs-1].ArgName))
  1458.       return 0;
  1459.   }
  1460.   else if(ap->NumArgs == 1)
  1461.   {
  1462.     if(!DoOutput(/*((*/") &tag);\n}\n"))
  1463.       return 0;
  1464.   }
  1465.   else if (!DoOutput(/*(*/") ((ULONG) &%s + sizeof("/*))*/,
  1466.   ap->Args[ap->NumArgs-2].ArgName) || !OutClibType(lastarg) ||
  1467.   !DoOutput(/*(((*/")));\n}\n"))
  1468.     return 0;
  1469.   return 1;
  1470. }
  1471.  
  1472. ULONG FuncLVOXDEF(struct AmiPragma *ap, ULONG data)
  1473. {
  1474.   return DoOutput("\t\tXDEF\t_LVO%s\n", ap->FuncName);
  1475. }
  1476.  
  1477. ULONG FuncLVO(struct AmiPragma *ap, ULONG data)
  1478. {
  1479.   return DoOutput("\n_LVO%-24s\tEQU\t-%ld", ap->FuncName, ap->Bias);
  1480. }
  1481.  
  1482. ULONG FuncLocCode(struct AmiPragma *ap, ULONG tagmode)
  1483. {
  1484.   ULONG a[5];
  1485.   STRPTR text = tagmode ? ap->TagName : ap->FuncName, str,
  1486.      str2 = Flags & FLAG_LOCALREG ? "rE" : "";
  1487.   LONG i = strlen(ShortBaseNameUpper);
  1488.   ULONG j;
  1489.  
  1490.   a[0] = HUNK_UNIT; a[1] = 0; a[2] = HUNK_NAME;
  1491.   a[3] = (i + 4 + 3)>>2;
  1492.  
  1493.   DoOutputDirect(a, 16);
  1494.   DoOutputDirect(ShortBaseNameUpper, i);
  1495.   DoOutputDirect("_LOC\0\0\0", (a[3]<<2)-i);
  1496.  
  1497.   if(Flags & FLAG_LOCALREG)
  1498.   {
  1499.     if(tagmode)
  1500.     {
  1501.       j = ap->Args[ap->NumArgs-1].ArgReg;
  1502.       a[0] = HUNK_CODE; a[1] = 4;
  1503.       a[2] = 0x2F000000 + (j << 16);    // MOVE    <ea>,-(A7)
  1504.  
  1505.       DoOutputDirect(a, 10);
  1506.  
  1507.       a[1] = 0x4EAE0000 + (UWORD) (- ap->Bias); //JSR instruction
  1508.       a[2] = 0x201F4E75;        // MOVE (A7)+,<ea>
  1509.       a[3] = 0;
  1510.       if(j > 7)
  1511.       {                // LEA x(A7),Ax
  1512.     j -= 8;
  1513.         a[0] = 0x41EF0008 | (j << 25);
  1514.         a[2] += 0x400000;  // set A flag
  1515.       }
  1516.       else
  1517.       {                // MOVE.L A7,Dx  -- ADDQ.L #8,Dx
  1518.         a[0] = 0x200F5080 | j | (j << 25);
  1519.       }
  1520.       a[2] += j << 25;
  1521.       
  1522.       DoOutputDirect(a, 14);
  1523.     }
  1524.     else
  1525.     {
  1526.       a[0] = HUNK_CODE; a[1] = 1;
  1527.       a[2] = 0x4EEE0000 + (UWORD) (- ap->Bias); //JMP instruction
  1528.       DoOutputDirect(a, 12);
  1529.     }
  1530.   }
  1531.   else
  1532.   {
  1533.     ULONG registers;
  1534.     ULONG offset = 1;
  1535.  
  1536.     registers = GetRegisterData(ap) | 0x40000002;
  1537.  
  1538.     a[0] = HUNK_CODE; a[1] = ap->NumArgs + 5;
  1539.  
  1540.     if(tagmode && ap->Args[ap->NumArgs-1].ArgReg <= 7)
  1541.       ++a[1];    /* one longword more, when D register and tagcall */
  1542.  
  1543.     DoOutputDirect(a, 8);
  1544.  
  1545.     a[0] = 0x48E70000 + (registers & 0xFFFF);
  1546.     for(j = (UWORD) registers; j; j >>= 1)
  1547.     {
  1548.       if(j & 1)
  1549.         ++offset;
  1550.     }
  1551.     a[1] = 0x2C6F0000+ ((offset++)<<2);
  1552.     DoOutputDirect(a, 8);
  1553.  
  1554.     for(i = 0; i < ap->NumArgs - (tagmode ? 1 : 0); ++i) // MOVE.L code generieren
  1555.     {
  1556.       a[0] = 0x202F0000 + ((i+offset)<<2);
  1557.  
  1558.       j = ap->Args[i].ArgReg;
  1559.       if(j > 7)
  1560.       {
  1561.         a[0] |= 0x400000; j -= 8;    // set MOVEA bit
  1562.       }
  1563.       a[0] |= j << 25;        // set destination register
  1564.  
  1565.       DoOutputDirect(a, 4);
  1566.     }
  1567.  
  1568.     if(i < ap->NumArgs)
  1569.     {
  1570.       if((j = ap->Args[i].ArgReg) > 7)
  1571.       {                // LEA x(A7),Ax
  1572.         a[0] = (0x41EF0000 | ((j-8) << 25)) + ((i+offset) << 2);
  1573.       }
  1574.       else
  1575.       {                // MOVE.L A7,Dx  -- ADD.L #x,Dx
  1576.         a[0] = 0x200FD0BC | (j << 25) | (j<<9);
  1577.         a[1] = (i+offset) << 2;
  1578.       }
  1579.  
  1580.       DoOutputDirect(a, j <= 7 ? 8 : 4);
  1581.     }
  1582.  
  1583.     // here comes the base reference
  1584.     a[0] = 0x4EAE0000 + (UWORD) (- ap->Bias); //JSR instruction
  1585.  
  1586.     DoOutputDirect(a, 4);
  1587.  
  1588.     a[0] = 0x4CDF0000 + (registers >> 16);
  1589.     a[1] = 0x4E750000;
  1590.     DoOutputDirect(a, 8);
  1591.   }
  1592.  
  1593.   a[0] = HUNK_EXT;
  1594.   DoOutputDirect(a,4);
  1595.  
  1596.   // here come the XDEF name references
  1597.  
  1598.   OutputXDEF("%s", text);    // asm names
  1599.   OutputXDEF("LOC_%s", text);
  1600.  
  1601.   OutputXDEF("_%s", text);    // C names
  1602.   OutputXDEF("_LOC_%s", text);
  1603.  
  1604.   if(!ap->NumArgs && clibbuf)
  1605.   {
  1606.     OutputXDEF("%s_%sP07Library", text, str2);    // C++ names no parameters
  1607.     OutputXDEF("LOC_%s__%sP07Library", text, str2);
  1608.   }
  1609.   else if((str = FindClibFunc(text)))
  1610.   {
  1611.     UBYTE name[100];
  1612.     ULONG ret = 0;
  1613.  
  1614.     do
  1615.     {
  1616.       if((ret = CopyCPPType(name, str, ret, text, ap->Args)))
  1617.       {    // C++ names with parameters
  1618.     OutputXDEF("%s__%sP07Library%s", text, str2, name);
  1619.         OutputXDEF("LOC_%s__%sP07Library%s", text, str2, name);
  1620.       }
  1621.     } while(ret == 0xFFFFFFFF);
  1622.   }
  1623.  
  1624.   a[0] = 0; a[1] = HUNK_END;
  1625.  
  1626.   return DoOutputDirect(a, 8);
  1627. }
  1628.  
  1629. ULONG FuncLocText(struct AmiPragma *ap, ULONG tagmode)
  1630. {
  1631.   STRPTR text = tagmode ? ap->TagName : ap->FuncName;
  1632.   STRPTR string;
  1633.   LONG i;
  1634.  
  1635.   if(!(string = FindClibFunc(text)))
  1636.     string = deftype;
  1637.  
  1638.   string = SkipBlanks(string);
  1639.  
  1640.   OutClibType(string);
  1641.   DoOutput(" LOC_%s("/*)*/, text);
  1642.   if(Flags & FLAG_LOCALREG)
  1643.     DoOutput("register __a6 ");
  1644.   DoOutput("struct Library * libbase");
  1645.   if(ap->NumArgs)
  1646.   {
  1647.     DoOutput(", ");
  1648.  
  1649.     for(i = 0; i < ap->NumArgs-1; i++)
  1650.     {
  1651.       if(!(string = GetClibType(string)) ||
  1652.       ((Flags & FLAG_LOCALREG &&
  1653.       !DoOutput("register __%s ", &RegNames[(ap->Args[i].ArgReg)<<2]))) ||
  1654.       !OutClibType(string) || !DoOutput(" %s, ", ap->Args[i].ArgName))
  1655.         return 0;
  1656.     }
  1657.  
  1658.     if(!tagmode)
  1659.     {
  1660.       if(!(string = GetClibType(string)) ||
  1661.       ((Flags & FLAG_LOCALREG &&
  1662.       !DoOutput("register __%s ", &RegNames[(ap->Args[i].ArgReg)<<2]))) ||
  1663.       !OutClibType(string) ||
  1664.       !DoOutput(/*(*/" %s);\n#define %s("/*)*/, ap->Args[i].ArgName, text))
  1665.         return 0;
  1666.       for(i = 0; i < ap->NumArgs-1; ++i)
  1667.         DoOutput("%lc, ", (i+'a'));
  1668.       DoOutput(/*(*/"%lc) LOC_%s((struct Library *) %s, "/*)*/,(i+'a'),
  1669.       text, BaseName);
  1670.       for(i = 0; i < ap->NumArgs-1; ++i)
  1671.         DoOutput("%lc, ",(i+'a'));
  1672.       return DoOutput(/*(*/"%lc)\n\n",(i+'a'));
  1673.     }
  1674.     else
  1675.       return DoOutput(/*(*/"...);\n");
  1676.   }
  1677.   else
  1678.     return DoOutput(/*(*/");\n");
  1679. }
  1680.  
  1681. ULONG CallFunc(ULONG tagmode, STRPTR comment,
  1682. ULONG (*Func) (struct AmiPragma *, ULONG))
  1683. {
  1684.   struct Comment *com = 0;
  1685.   struct AmiPragma *ap;
  1686.  
  1687.   if(comment)
  1688.     com = (struct Comment *) Comment.First;
  1689.  
  1690.   for(ap = (struct AmiPragma *) AmiPragma.First; ap && !CTRL_C;
  1691.   ap = (struct AmiPragma *) ap->List.Next)
  1692.   {
  1693.     if(ap->Public || (Flags & FLAG_PRIVATE))
  1694.     {
  1695.       while(com && com->Bias <= ap->Bias)
  1696.       {
  1697.         if(!DoOutput(comment, com->Data))
  1698.           return 0;
  1699.         com = (struct Comment *) com->List.Next;
  1700.       }
  1701.  
  1702.       if(tagmode && ap->TagName && !Func(ap, tagmode))
  1703.         return 0;
  1704.       if(tagmode != TAGMODE_TAGS && ap->FuncName && !Func(ap, 0))
  1705.         return 0;
  1706.     }
  1707.   }
  1708.   while(com)
  1709.   {
  1710.     if(!DoOutput(comment, com->Data))
  1711.       return 0;
  1712.     com = (struct Comment *) com->List.Next;
  1713.   }
  1714.   return 1;
  1715. }
  1716.  
  1717. /* ------------------------------------------------------------------ */
  1718.  
  1719. // return non zero, when ok, return 0xFFFFFFFF when STRPTR and not flags
  1720. ULONG CopyCPPType(STRPTR buffer, STRPTR a, ULONG flag, STRPTR func,
  1721. struct AmiArgs *args)
  1722. {
  1723. // when flag, then STRPTR is unsigned char * mode, else signed char *
  1724.   ULONG ret = 1;
  1725.   ULONG k = 0;
  1726.   struct CPP_NameType nt;
  1727.  
  1728.   while((a = GetClibType(a)))
  1729.   {
  1730.     SDI_memset(&nt, 0, sizeof(struct CPP_NameType));
  1731.     GetCPPType(&nt, a);
  1732.  
  1733.     if(!flag && (nt.Flags & CPP_FLAG_STRPTR))
  1734.       ret = 0xFFFFFFFF;
  1735.  
  1736.     if(!nt.StructureName && !nt.Type)
  1737.     {
  1738.       APTR str;
  1739.       ULONG l = GetClibLength(a);
  1740.  
  1741.       if((str = AllocMem(l+1, MEMF_ANY|MEMF_CLEAR)))
  1742.         CopyMem(a, str, l);
  1743.  
  1744.       DoError(ERR_UNKNOWN_VARIABLE_TYPE, 0, str ? str : "?", func);
  1745.  
  1746.       if(str)
  1747.         FreeMem(str, l);
  1748.  
  1749.       return 0;
  1750.     }
  1751.     if((Flags & FLAG_LOCALREG) && (nt.Type != CPP_TYPE_VARARGS))
  1752.     {
  1753.       *(buffer++) = 'r';
  1754.       *(buffer++) = args[k].ArgReg + (args[k].ArgReg < 10 ? '0' : 'A'-10);
  1755.     }
  1756.     while(nt.PointerDepth--)
  1757.       *(buffer++) = 'P';
  1758.     if(nt.Flags & CPP_FLAG_CONST)
  1759.       *(buffer++) = 'C';
  1760.     if((nt.Flags & CPP_FLAG_UNSIGNED) || (flag && (nt.Flags & CPP_FLAG_STRPTR)))
  1761.       *(buffer++) = 'U';
  1762.     if(nt.Type)
  1763.       *(buffer++) = nt.Type;
  1764.     else
  1765.     {
  1766.       ULONG i;
  1767.       sprintf(buffer, "%02ld", nt.StructureLength); buffer += 2;
  1768.       for(i = 0; i < nt.StructureLength; ++i)
  1769.         *(buffer++) = nt.StructureName[i];
  1770.     }
  1771.     ++k;
  1772.   }
  1773.  
  1774.   *(buffer) = 0;
  1775.   return ret;
  1776. }
  1777.  
  1778. void GetCPPType(struct CPP_NameType *data, STRPTR start)
  1779. {
  1780.   ULONG a = 0;
  1781.   STRPTR u;
  1782.  
  1783.   while(a < 100)
  1784.   {
  1785.     start = SkipBlanks(start);
  1786.     if(!strncmp("...",start,3))
  1787.     {
  1788.       data->Type = CPP_TYPE_VARARGS; return;
  1789.     }
  1790.     if(!strncmp("const",start, 5))
  1791.     {
  1792.       data->Flags |= CPP_FLAG_CONST; start += 6;
  1793.     }
  1794.     else if(!strncmp("signed", start,6))
  1795.       start += 7;
  1796.     else if(!strncmp("unsigned",start,8))
  1797.     {
  1798.       data->Flags |= CPP_FLAG_UNSIGNED; start += 9;
  1799.     }
  1800.     else if(!strncmp("struct",start,6))
  1801.     {
  1802.       data->StructureName = SkipBlanks(start+6);
  1803.       start = SkipName(data->StructureName);
  1804.       data->StructureLength = start-data->StructureName;
  1805.       a = 100;
  1806.     }
  1807.     else if(!a)
  1808.     {
  1809.       ULONG i;
  1810.  
  1811.       for(i = 0; CPP_Field[i].Text; ++i)
  1812.       {
  1813.         if(!strncmp(start, CPP_Field[i].Text, CPP_Field[i].Length))
  1814.         {
  1815.           start += CPP_Field[i].Length + 1;
  1816.           data->Type = CPP_Field[i].Type;
  1817.           data->Flags |= (CPP_Field[i].Flags & ~CPP_FLAG_POINTER);
  1818.           if(data->Flags & CPP_FLAG_POINTER)
  1819.             ++data->PointerDepth;
  1820.           break;
  1821.         }
  1822.       }
  1823.       a = 2;
  1824.     }
  1825.     else
  1826.       a = 100;
  1827.   }
  1828.  
  1829.   do
  1830.   {
  1831.     u = SkipBlanks(start);
  1832.     if(*u == '*')
  1833.     {
  1834.       start = u+1; ++data->PointerDepth;
  1835.     }
  1836.   } while(*u == '*');
  1837. }
  1838.  
  1839. STRPTR FindClibFunc(STRPTR func) // finds the needed function
  1840. {
  1841.   ULONG len = strlen(func);
  1842.   STRPTR string, linestart, strend = clibbuf + clibsize;
  1843.   ULONG commentmode = 0;
  1844.  
  1845. #ifdef DEBUG_OLD
  1846.   VPrintf("FindClibFunc: %s\n", &func);
  1847. #endif
  1848.  
  1849.   if(!(linestart = string = clibbuf))
  1850.     return 0;
  1851.  
  1852.   do
  1853.   {
  1854.     while(*string && (commentmode || *string != '('/*)*/))
  1855.     {
  1856.       if(*(string++) == '/')
  1857.       {
  1858.         if(*string == '*') // start of comment
  1859.           commentmode = 1;
  1860.         else if(*(string-2) == '*')  // end of comment
  1861.           commentmode = 0;
  1862.         else if(*string == '/') // skip line comments
  1863.         {
  1864.           while(*string)
  1865.             ++string;
  1866.         }
  1867.       }
  1868.     }
  1869.         
  1870.     if(*string == '(' /*)*/)
  1871.     {
  1872.       while(*(--string) == ' ' || *string == '\t')
  1873.         ;
  1874.       if(!strncmp(func, string-len+1, len) && (*(string-len) == ' ' ||
  1875.       *(string-len) == '\t' || !*(string-len)))
  1876.         return linestart;
  1877.     }
  1878.     while(string < strend && *string)
  1879.       ++string;
  1880.     if(!*string)
  1881.       linestart = ++string;
  1882.   } while(string < strend);
  1883.   
  1884.   return 0;
  1885. }
  1886.  
  1887. ULONG GetClibLength(STRPTR start) // returns length of the type
  1888. {
  1889.   STRPTR old = start, u;
  1890.   ULONG a = 1;
  1891.  
  1892. #ifdef DEBUG_OLD
  1893.   VPrintf("GetClibLength:\n", 0);
  1894. #endif
  1895.  
  1896.   while(a)
  1897.   {
  1898.     start = SkipBlanks(start); a = 0;
  1899.     if(!strncmp("const",start, 5))
  1900.     {
  1901.       ++a; start += 6;
  1902.     }
  1903.     if(!strncmp("struct",start,6) || !strncmp("signed", start,6))
  1904.     {
  1905.       ++a; start += 7;
  1906.     }
  1907.     if(!strncmp("unsigned",start,8))
  1908.     {
  1909.       ++a; start += 9;
  1910.     }
  1911.   }
  1912.  
  1913.   while(*start && *start != ' ' && *start != '\t' && *start != '*')
  1914.    ++start;
  1915.  
  1916.   do
  1917.   {
  1918.     u = SkipBlanks(start);
  1919.     if(*u == '*')
  1920.       start = u+1;
  1921.   } while(*u == '*');
  1922.  
  1923.   return (ULONG) (start-old);
  1924. }
  1925.  
  1926. ULONG OutClibType(STRPTR start)
  1927. {
  1928.   UBYTE string[11];
  1929.   ULONG length = GetClibLength(start), i;
  1930.  
  1931. #ifdef DEBUG_OLD
  1932.   VPrintf("OutClibType:\n", 0);
  1933. #endif
  1934.  
  1935.   while(length)
  1936.   {
  1937.     if(length > 10)
  1938.       i = 10;
  1939.     else
  1940.       i = length;
  1941.  
  1942.     CopyMem(start, string, i);
  1943.     string[i] = '\0'; length -= i; start += i;
  1944.     if(!DoOutput(string))
  1945.       return 0;
  1946.   }
  1947.   return 1;
  1948. }
  1949.  
  1950. STRPTR GetClibType(STRPTR start) // searches for next type definition
  1951. {
  1952.   if(start == deftype)
  1953.     return start;
  1954. #ifdef DEBUG_OLD
  1955.   VPrintf("GetClibType:\n", 0);
  1956. #endif
  1957.   while(*start && *start != '(' && *start != ',' && *start != ')')
  1958.     ++start;
  1959.   if(!*start || *start == /*(*/')')
  1960.     return 0;
  1961.   return SkipBlanks(++start);
  1962. }
  1963.  
  1964. /* ------------------------------------------------------------------ */
  1965.  
  1966. ULONG CallPrag(ULONG tagmode, STRPTR type,
  1967. ULONG (*Func) (struct AmiPragma *, ULONG))
  1968. {
  1969.   if(type)
  1970.     if((*type && !DoOutput("#if%s\n", type)) ||
  1971.     !(CallFunc(tagmode, tagmode ? 0 : "/%s */\n", Func)) ||
  1972.     (*type && !DoOutput("#endif\n")) || CTRL_C)
  1973.       return 0;
  1974.   return 1;
  1975. }
  1976.  
  1977. ULONG CreatePragmaFile(void)
  1978. {
  1979.   switch(MODE)
  1980.   {
  1981.   case 1: DoOutput("#ifndef _INCLUDE_PRAGMA_%s_LIB_H\n#define _INCLUDE_PRAGMA_%s_LIB_H\n",
  1982.     ShortBaseNameUpper, ShortBaseNameUpper); break;
  1983.   case 2: DoOutput("#ifndef PRAGMAS_%s_LIB_H\n#define PRAGMAS_%s_LIB_H\n",
  1984.     ShortBaseNameUpper, ShortBaseNameUpper); break;
  1985.   case 3: DoOutput("#ifndef PRAGMAS_%s_PRAGMAS_H\n#define PRAGMAS_%s_PRAGMAS_H\n",
  1986.     ShortBaseNameUpper, ShortBaseNameUpper); break;
  1987.   case 4: break;
  1988.   default: return 0;
  1989.   }
  1990.  
  1991.   if(HEADER)
  1992.   {
  1993.     DoOutput("\n");
  1994.     DoOutputDirect(HEADER, headersize);
  1995.   }
  1996.  
  1997.   if(MODE != 4 && !DoOutput("\n#ifndef CLIB_%s_PROTOS_H\n#include "
  1998.   "<clib/%s_protos.h>\n#endif\n\n", ShortBaseNameUpper, ShortBaseName))
  1999.     return 0;
  2000.  
  2001.   if((Flags & FLAG_PROTOTYPE) && !DoOutput("extern struct Library *%s;\n\n",
  2002.   BaseName))
  2003.     return 0;
  2004.  
  2005.   if((Flags & FLAG_EXTERNC) &&
  2006.   !DoOutput("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"))
  2007.     return 0;
  2008.  
  2009.   if(
  2010.   !CallPrag(TAGMODE_NORMAL, AMICALL, FuncAMICALL) ||
  2011.   !CallPrag(TAGMODE_NORMAL, LIBCALL, FuncLIBCALL))
  2012.     return 0;
  2013.  
  2014.   if(tagfuncs)
  2015.   {
  2016.     if(
  2017.     !CallPrag(TAGMODE_TAGS, AMITAGS, FuncAMICALL) ||
  2018.     !CallPrag(TAGMODE_TAGS, LIBTAGS, FuncLIBCALL) ||
  2019.     !CallPrag(TAGMODE_TAGS, CSTUBS,  FuncCSTUBS))
  2020.       return 0;
  2021.   }
  2022.  
  2023.   if((Flags & FLAG_EXTERNC) &&
  2024.   !DoOutput("\n#ifdef __cplusplus\n}\n#endif\n"))
  2025.     return 0;
  2026.  
  2027.   switch(MODE)
  2028.   {
  2029.   case 1: DoOutput("\n#endif\t/*  _INCLUDE_PRAGMA_%s_LIB_H  */",
  2030.     ShortBaseNameUpper); break;
  2031.   case 2: DoOutput("\n#endif\t/*  PRAGMAS_%s_LIB_H  */",
  2032.     ShortBaseNameUpper); break;
  2033.   case 3: DoOutput("\n#endif\t/*  PRAGMAS_%s_PRAGMA_H  */",
  2034.     ShortBaseNameUpper); break;
  2035.   case 4: break;
  2036.   default: return 0;
  2037.   }
  2038.   return Output_Error;
  2039. }
  2040.  
  2041. ULONG CreateLVOFile(ULONG mode)
  2042. {
  2043.   STRPTR data = "_LVO_I";
  2044.  
  2045.   if(mode == 2 || mode == 4)
  2046.     data = "_LIB_I";
  2047.  
  2048.   if(!DoOutput("\t\tIFND LIBRARIES_%s%s\nLIBRARIES_%s%s\tSET\t1\n\n",
  2049.   ShortBaseNameUpper, data, ShortBaseNameUpper, data) ||
  2050.   (HEADER && (!DoOutput("\n") || !DoOutputDirect(HEADER, headersize))) ||
  2051.   (mode <= 2 && !CallFunc(TAGMODE_NORMAL, 0, FuncLVOXDEF)) ||
  2052.   !CallFunc(TAGMODE_NORMAL, "\n%s", FuncLVO) ||
  2053.   !DoOutput("\n\n\t\tENDC") || CTRL_C)
  2054.     return 0;
  2055.  
  2056.   return 1;
  2057. }
  2058.  
  2059. ULONG CreateAsmStubs(ULONG mode)
  2060. {
  2061.   // 1 = Text, 2 = Code
  2062.   switch(mode)
  2063.   {
  2064.   case 1:
  2065.     if((HEADER && (!DoOutput("\n") || !DoOutputDirect(HEADER, headersize))) ||
  2066.     !DoOutput("\tSECTION\t \"%s_STUBS\",CODE\n\tXREF\t_%s\n",
  2067.     ShortBaseNameUpper, BaseName) ||
  2068.     !CallFunc(MODE, 0, FuncAsmText))
  2069.       return 0;
  2070.     break;
  2071.   case 2:
  2072.     if(!CallFunc(MODE, 0, FuncAsmCode))
  2073.       return 0;
  2074.     break;
  2075.   }
  2076.  
  2077.   if(CTRL_C)
  2078.     return 0;
  2079.   return 1;
  2080. }
  2081.  
  2082. ULONG CreateProtoFile(ULONG Type)
  2083. {
  2084.   STRPTR str1 = "pragma", str2 = "lib";
  2085.  
  2086.   DoOutput("#ifndef _PROTO_%s_H\n#define _PROTO_%s_H\n", ShortBaseNameUpper,
  2087.   ShortBaseNameUpper);
  2088.  
  2089.   if(HEADER)
  2090.   {
  2091.     DoOutput("\n");
  2092.     DoOutputDirect(HEADER, headersize);
  2093.   }
  2094.  
  2095.   switch(Type)
  2096.   {
  2097.     case 4: str1 = "pragmas"; // no break;
  2098.     case 2: str2 = "pragmas"; break;
  2099.     case 3: str1 = "pragmas"; break;
  2100.     case 5: str1 = "local"; str2 = "loc"; break;
  2101.   }
  2102.  
  2103.   DoOutput("\n#include <exec/types.h>\n\nextern struct Library *%s;\n\n",
  2104.   BaseName);
  2105.  
  2106.   if(Type != 5)
  2107.     DoOutput("#include <clib/%s_protos.h>\n",ShortBaseName);
  2108.  
  2109.   return DoOutput("#include <%s/%s_%s.h>\n\n#endif\n", str1, ShortBaseName,
  2110.   str2);
  2111. }
  2112.  
  2113. ULONG CreateLocalData()
  2114. {
  2115.   UBYTE a[40];
  2116.  
  2117.   DoOutput("#ifndef _INCLUDE_PROTO_%s_LOC_H\n#define _INCLUDE_PROTO_%s_LOC_H\n\n",
  2118.   ShortBaseNameUpper, ShortBaseNameUpper);
  2119.   
  2120.   if(HEADER)
  2121.   {
  2122.     DoOutput("\n");
  2123.     DoOutputDirect(HEADER, headersize);
  2124.   }
  2125.  
  2126.   { // copies the include lines
  2127.     STRPTR str = clibbuf, strend = clibbuf + clibsize;
  2128.     ULONG i = 0;
  2129.  
  2130.     // works too, when no clibbuf, because then following is everytime false
  2131.     while(str < strend)
  2132.     {
  2133.       if(!strncmp(str, "#include", 8))
  2134.       {
  2135.     DoOutput("%s\n",str); ++i;
  2136.       }
  2137.       while(*(str++))
  2138.         ;
  2139.     }
  2140.     DoOutput(i ? "\n" : "#include <exec/types.h>\n\n");
  2141.   }
  2142.  
  2143.   if((Flags & FLAG_EXTERNC) &&
  2144.   !DoOutput("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"))
  2145.     return 0;
  2146.  
  2147.   if(!CallFunc(MODE, 0, FuncLocText))
  2148.     return 0;
  2149.  
  2150.   if((Flags & FLAG_EXTERNC) &&
  2151.   !DoOutput("#ifdef __cplusplus\n}\n#endif\n\n"))
  2152.     return 0;
  2153.  
  2154.   DoOutput("#endif\t/*  _INCLUDE_PROTO_%s_LOC_H  */", ShortBaseNameUpper);
  2155.   Out(out.size); // clears buffer
  2156.  
  2157.   sprintf(a, "%s_loc.lib", ShortBaseName);
  2158.   Close(out.file);
  2159.   if(!(out.file = Open(a, MODE_NEWFILE)))
  2160.     return 0;
  2161.  
  2162.   return CallFunc(MODE, 0, FuncLocCode);
  2163. }
  2164.  
  2165. /* ------------------------------------------------------------------ */
  2166.  
  2167. ULONG GetName(struct NameList *t, struct ShortListRoot *p, ULONG args)
  2168. {
  2169.   struct NameList *p2 = (struct NameList *) p->First;
  2170.   struct AmiPragma ap;
  2171.   ap.FuncName = t->NormName;
  2172.   ap.NumArgs = 1;
  2173.   ap.Args[0].ArgName = (args ? "args" : "tags");
  2174.   if(!MakeTagFunction(&ap))
  2175.     return 0;
  2176.  
  2177.   while(p2 && strcmp(p2->PragName, ap.TagName))
  2178.    p2 = (struct NameList *) p2->List.Next;
  2179.  
  2180.   if(!p2)
  2181.     return 0;
  2182.  
  2183.   t->Type = (args ? NTP_ARGS : NTP_TAGS);
  2184.   t->PragName = ap.TagName;
  2185.   RemoveItem(p, (struct ShortList *) p2);
  2186.  
  2187. #ifdef DEBUG
  2188.   VPrintf("GetName: name matches - %s _ %s\n", &t->NormName);
  2189. #endif
  2190.  
  2191.   return 1;
  2192. }
  2193.  
  2194. void OptimizeFDData(struct PragData *pd)
  2195. {
  2196. #ifdef DEBUG
  2197.   PutStr("OptimizeFDData\n");
  2198. #endif
  2199.  
  2200.   while(pd && !CTRL_C)
  2201.   {
  2202.     if(pd->NumNames > 1)
  2203.     {
  2204.       struct ShortListRoot n = {0,0,0}, p = {0,0,0};
  2205.       struct NameList *t;
  2206.       while(pd->Name.First)    // sorts in AmiCall and TagCall
  2207.       {
  2208.     t = (struct NameList *) pd->Name.First;
  2209.  
  2210.     RemoveItem(&pd->Name, (struct ShortList *) t);
  2211.     AddItem(t->PragName ? &p : &n, (struct ShortList *) t);
  2212.       }
  2213.  
  2214.       if(p.First)
  2215.       {
  2216.     t = (struct NameList *) n.First;
  2217.     while(p.First && t)
  2218.         {
  2219.       if(!GetName(t, &p, 0))
  2220.       {
  2221.         GetName(t, &p, 1);
  2222.           }
  2223.           if(t->PragName)
  2224.       {
  2225.         struct NameList *t2 = (struct NameList *) t->List.Next;
  2226.         RemoveItem(&n, (struct ShortList *)t);
  2227.         AddItem(&pd->Name, (struct ShortList *) t);
  2228.         t = t2;
  2229.           }
  2230.       else
  2231.         t = (struct NameList *) t->List.Next;
  2232.         }
  2233.     while(p.First)
  2234.     {
  2235.       if(n.First)
  2236.       {
  2237.         t = (struct NameList *) n.First;
  2238.         t->PragName = ((struct NameList *)(p.First))->PragName;
  2239.         RemoveItem(&n, (struct ShortList *) t);
  2240. #ifdef DEBUG
  2241.         VPrintf("OptimizeFDData: names together - %s _ %s\n", &t->NormName);
  2242. #endif
  2243.         t->Type = NTP_UNKNOWN;
  2244.           }
  2245.           else
  2246.           {
  2247.         ULONG i;
  2248.  
  2249.             t = (struct NameList *) p.First;
  2250.         i = strlen(t->PragName);
  2251.         t->NormName = strndup(t->PragName, i+1);
  2252.         t->NormName[i++] = 'A';
  2253.         t->NormName[i] = 0;
  2254.         t->Type = NTP_TAGS;
  2255. #ifdef DEBUG
  2256.         VPrintf("OptimizeFDData: NormName created - %s _ %s\n", &t->NormName);
  2257. #endif
  2258.       }
  2259.  
  2260.       AddItem(&pd->Name, (struct ShortList *) t);
  2261.       RemoveItem(&p, p.First);
  2262.         }
  2263.       }
  2264.  
  2265.       AddItem(&pd->Name, n.First); /* add left NormNames */
  2266.     }
  2267.     pd = (struct PragData *) pd->List.Next;
  2268.   }
  2269. }
  2270.  
  2271. ULONG MakeFD(struct PragList *pl)
  2272. {
  2273.   struct PragData *pd = (struct PragData *) pl->Data.First;
  2274.   ULONG bias;
  2275.  
  2276. #ifdef DEBUG
  2277.   PutStr("MakeFD\n");
  2278. #endif
  2279.   bias = pd->Bias;
  2280.  
  2281.   OptimizeFDData(pd);
  2282. #ifdef DEBUG
  2283.   PutStr("MakeFD: after Optimizing\n");
  2284. #endif
  2285.   DoOutput("##base _%s\n##bias %ld\n##public\n", pl->Basename, bias);
  2286.  
  2287.   while(pd && !CTRL_C && Output_Error)
  2288.   {
  2289.     struct NameList *n = (struct NameList *) pd->Name.First;
  2290.  
  2291.     if(bias != pd->Bias)
  2292.       DoOutput("##bias %ld\n", (bias = pd->Bias));
  2293.  
  2294.     while(n)
  2295.     {
  2296.       STRPTR lastpar = "last";
  2297.       ULONG i;
  2298.  
  2299.       if(n->Type == NTP_TAGS)
  2300.         lastpar = "tags";
  2301.       else if(n->Type == NTP_ARGS)
  2302.         lastpar = "args";
  2303.  
  2304.       DoOutput("%s("/*)*/,n->NormName);
  2305.       if(!pd->NumArgs)
  2306.         DoOutput(/*(*/")()\n");
  2307.       else
  2308.       {
  2309.         for(i = 0; i < pd->NumArgs-1; ++i)
  2310.           DoOutput("par%ld,",i+1);
  2311.         DoOutput("%s)(", lastpar);
  2312.         for(i = 0; i < pd->NumArgs-1; ++i)
  2313.           DoOutput("%s,", &RegNames[(pd->ArgReg[i])<<2]);
  2314.         DoOutput("%s)\n", &RegNames[(pd->ArgReg[i])<<2]);
  2315.  
  2316.         if(n->Type == NTP_UNKNOWN)
  2317.         {
  2318.           ULONG i;
  2319.           for(i = 0; n->NormName[i] == n->PragName[i]; ++i)
  2320.             ;
  2321.           DoOutput("*tagcall");
  2322.           if(n->NormName[i])
  2323.             DoOutput("-%s", n->NormName+i);
  2324.           if(n->PragName[i])
  2325.             DoOutput("+%s", n->PragName+i);
  2326.  
  2327.           DoOutput("\n");
  2328.         }
  2329.       }
  2330.       if((n = (struct NameList *) n->List.Next))
  2331.         DoOutput("##bias %ld\n", pd->Bias);
  2332.     }
  2333.  
  2334.     pd = (struct PragData *)pd->List.Next; bias += 6;
  2335.   }
  2336.   if(CTRL_C)
  2337.     return 0;
  2338.   return Output_Error;
  2339. }
  2340.  
  2341. ULONG AddFDData(struct ShortListRoot *pls, struct FDData *fd)
  2342. {
  2343.   struct NameList *t;
  2344.   struct PragList *pl = (struct PragList *) pls->First;
  2345.   struct PragData *pd;
  2346.  
  2347.   while(pl && strcmp(pl->Basename, fd->Basename))
  2348.     pl = (struct PragList *) pl->List.Next;
  2349.  
  2350.   if(!pl)
  2351.   {
  2352. #ifdef DEBUG
  2353.   VPrintf("AddFDData: New PragList - %s\n", &fd->Basename);
  2354. #endif
  2355.     if(!(pl = (struct PragList *) NewItem(pls)))
  2356.       return 100;
  2357.     pl->Basename = fd->Basename;
  2358.     pl->Data.Size = sizeof(struct PragData);
  2359.     AddItem(pls, (struct ShortList *) pl);
  2360.   }
  2361.  
  2362.   if((pd = (struct PragData *) pl->Data.First))
  2363.   {
  2364.     while(pd->List.Next && ((struct PragData *) pd->List.Next)->Bias
  2365.     <= fd->Bias)
  2366.       pd = (struct PragData *) pd->List.Next;
  2367.   }
  2368.  
  2369.   if(!pd || pd->Bias != fd->Bias)
  2370.   {
  2371.     struct PragData *pd2;
  2372. #ifdef DEBUG
  2373.     {
  2374.       ULONG args[2];
  2375.       args[0] = fd->Bias;
  2376.       args[1] = fd->NumArgs;
  2377.       VPrintf("AddFDData: New PragData - %ld, %ld\n", &args);
  2378.     }
  2379. #endif
  2380.     if(!(pd2 = (struct PragData *) NewItem(&pl->Data)))
  2381.       return 100;
  2382.     pd2->Bias = fd->Bias;
  2383.     CopyMem(fd->ArgReg, pd2->ArgReg, 14);
  2384.     pd2->NumArgs = fd->NumArgs;
  2385.     pd2->Name.Size = sizeof(struct NameList);
  2386.     if(!pd)
  2387.       AddItem(&pl->Data, (struct ShortList *) pd2);
  2388.     else if(pd->Bias > fd->Bias) /* Insert at start */
  2389.     {
  2390.       pd2->List.Next = pl->Data.First;
  2391.       pl->Data.First = (struct ShortList *) pd2;
  2392.     }
  2393.     else /* Insert the entry */
  2394.     {
  2395.       pd2->List.Next = pd->List.Next;
  2396.       pd->List.Next = (struct ShortList *) pd2;
  2397.     }
  2398.     pd = pd2;
  2399.   }
  2400.   else
  2401.   {
  2402.     ULONG i = fd->NumArgs;
  2403.     if(fd->NumArgs != pd->NumArgs)
  2404.       return ERR_DIFFERENT_TO_PREVIOUS;
  2405.  
  2406.     while(i--)
  2407.     {
  2408.       if(fd->ArgReg[i] != pd->ArgReg[i])
  2409.         return ERR_DIFFERENT_TO_PREVIOUS;
  2410.     }
  2411.   }
  2412.  
  2413.   t = (struct NameList *) pd->Name.First;    // skips same Names
  2414.   while(t && strcmp(fd->Name, fd->Mode ? t->PragName : t->NormName))
  2415.     t = (struct NameList *) t->List.Next;
  2416.  
  2417.   if(t)
  2418.     return 0;
  2419.  
  2420.   if(!(t = (struct NameList *) NewItem(&pd->Name)))
  2421.     return 100;
  2422.   if(fd->Mode)
  2423.     t->PragName = fd->Name;
  2424.   else
  2425.     t->NormName = fd->Name;
  2426.   AddItem(&pd->Name, (struct ShortList *) t);
  2427.   ++(pd->NumNames);
  2428. #ifdef DEBUG
  2429.   VPrintf("AddFDData: New NameList - %s\n", &fd->Name);
  2430. #endif
  2431.   return 0;
  2432. }
  2433.  
  2434. UBYTE GetHexValue(UBYTE data)
  2435. {
  2436.   if(data >= 'a')
  2437.     return (UBYTE) (data - 'a' + 10);
  2438.   else if(data >= 'A')
  2439.     return (UBYTE) (data - 'A' + 10);
  2440.   else
  2441.     return (UBYTE) (data - '0');
  2442. }
  2443.  
  2444. ULONG GetLibData(struct FDData *fd)
  2445. {
  2446.   ULONG i;
  2447.   fd->Name = SkipBlanks(in.pos);
  2448.   in.pos = SkipName(fd->Name); *(in.pos++) = 0;
  2449.   in.pos = SkipBlanks(in.pos);
  2450.   fd->Bias = strtoul(in.pos, 0, 16);
  2451.   while(*in.pos)
  2452.     ++in.pos;
  2453.   if((fd->NumArgs = GetHexValue(*(--in.pos))) > 14)
  2454.     return ERR_TO_MUCH_ARGUMENTS;
  2455.   --in.pos; // skips return register
  2456.   for(i = 0; i < fd->NumArgs; ++i)
  2457.   {
  2458.     if((fd->ArgReg[i] = GetHexValue(*(--in.pos))) > 14)
  2459.       return ERR_EXPECTED_REGISTER_NAME;
  2460.   }
  2461.   return 0;
  2462. }
  2463.  
  2464. ULONG GetAmiData(struct FDData *fd)
  2465. {
  2466.   STRPTR endptr;
  2467.   in.pos = SkipBlanks(in.pos);
  2468.   if(*in.pos != '('/*)*/)
  2469.     return ERR_EXPECTED_OPEN_BRACKET;
  2470.   fd->Basename = ++in.pos;
  2471.   in.pos = SkipBlanks(endptr = SkipName(in.pos));
  2472.   if(*in.pos != ',')
  2473.     return ERR_EXPECTED_COMMA;
  2474.   *endptr = 0;
  2475.   in.pos = SkipBlanks(++in.pos);
  2476.   if(!strncmp(in.pos, "0x", 2))
  2477.     fd->Bias = strtoul(in.pos+2, 0, 16);
  2478.   else
  2479.     fd->Bias = strtoul(in.pos, 0, 10);
  2480.  
  2481.   in.pos = SkipBlanks(SkipName(in.pos));
  2482.   if(*in.pos != ',')
  2483.     return ERR_EXPECTED_COMMA;
  2484.   fd->Name = in.pos = SkipBlanks(++in.pos);
  2485.   in.pos = SkipBlanks(endptr = SkipName(in.pos));
  2486.   if(*in.pos != '('/*)*/)
  2487.     return ERR_EXPECTED_OPEN_BRACKET;
  2488.   *endptr = 0;
  2489.   in.pos = SkipBlanks(++in.pos);
  2490.   if(*in.pos == /*(*/')')
  2491.     return 0;
  2492.   --in.pos;
  2493.   while(*in.pos != /*(*/')')
  2494.   {
  2495.     ULONG i;
  2496.     in.pos = SkipBlanks(in.pos+1);
  2497.     for(i = 0; i < 16; i++)
  2498.       if(!strnicmp(&RegNames[i<<2], in.pos, 2))
  2499.         break;
  2500.     if(i == 16)
  2501.       return ERR_EXPECTED_REGISTER_NAME;
  2502.     if(i > 14)
  2503.       return ERR_ILLEGAL_REGISTER;
  2504.  
  2505.     if(fd->NumArgs > 14)
  2506.       return ERR_TO_MUCH_ARGUMENTS;
  2507.  
  2508.     fd->ArgReg[fd->NumArgs] = i; ++fd->NumArgs;
  2509.  
  2510.     in.pos = SkipBlanks(in.pos+2);
  2511.  
  2512.     if(*in.pos != ',' && *in.pos != ')')
  2513.       return ERR_EXPECTED_CLOSE_BRACKET;
  2514.   }
  2515.   in.pos = SkipBlanks(in.pos+1);
  2516.   if(*in.pos != ')')
  2517.     return ERR_EXPECTED_CLOSE_BRACKET;
  2518.   return 0;
  2519. }
  2520.  
  2521. ULONG CreateFDFile(STRPTR file, STRPTR to)
  2522. {
  2523.   struct ShortListRoot pl = {0, 0, sizeof(struct PragList)};
  2524.   ULONG linenum, err = 0, skip;
  2525.  
  2526.   for(linenum = 1; !CTRL_C && in.pos < in.buf + in.size; ++linenum)
  2527.   {
  2528.     in.pos = SkipBlanks(in.pos);
  2529.     if(!strncmp("#pragma", in.pos, 7))
  2530.     {
  2531.       struct FDData fd;
  2532.       
  2533.       skip = 0;
  2534.       memset(&fd, 0, sizeof(struct FDData));
  2535.  
  2536.       in.pos = SkipBlanks(in.pos+7);
  2537.       if(!strncmp("tagcall", in.pos, 7))
  2538.       {
  2539.     fd.Mode = 1;
  2540.         in.pos = SkipBlanks(in.pos+7);
  2541.         if(*in.pos == '(' /*)*/)    // Storm method
  2542.       err = GetAmiData(&fd);
  2543.         else                // SAS method
  2544.     {
  2545.           fd.Basename = in.pos;
  2546.       in.pos = SkipName(fd.Basename); *(in.pos++) = 0;
  2547.           err = GetLibData(&fd);
  2548.     }
  2549.       }
  2550.       else if(!strncmp("amicall", in.pos, 7))    // Storm method
  2551.       {
  2552.     in.pos += 7;
  2553.     err = GetAmiData(&fd);
  2554.       }
  2555.       else if(!strncmp("libcall", in.pos, 7))    // SAS method
  2556.       {
  2557.         fd.Basename = SkipBlanks(in.pos+7);
  2558.     in.pos = SkipName(fd.Basename); *(in.pos++) = 0;
  2559.         err = GetLibData(&fd);
  2560.       }
  2561.       else if(!strncmp("syscall", in.pos, 7))    // SAS method
  2562.       {
  2563.         fd.Basename = "SysBase";
  2564.         err = GetLibData(&fd);
  2565.       }
  2566.       else
  2567.         skip = 1;
  2568.  
  2569.       if(err)
  2570.     DoError(err, linenum);
  2571.       else if(skip)
  2572.         ;
  2573.       else if((err = AddFDData(&pl, &fd)))
  2574.       {
  2575.     if(err != 100)
  2576.       DoError(err, linenum);
  2577.     return 0;
  2578.       }
  2579.     }
  2580.     while(*(in.pos++))    // jumps to first char of next line
  2581.       ;
  2582.   }
  2583.  
  2584.   if(pl.First && !CTRL_C)
  2585.   {
  2586.     struct PragList *p = (struct PragList *) pl.First;
  2587.     if(!p->List.Next)
  2588.     {
  2589.       if(!to)
  2590.       {
  2591.         STRPTR text;
  2592.           ULONG i;
  2593.           
  2594.         if(ShortBaseName)
  2595.         {
  2596.           text = ShortBaseName; i = strlen(text);
  2597.         }
  2598.         else
  2599.         {
  2600.             text = p->Basename; i = strlen(text)-4;
  2601.           }
  2602.  
  2603.         to = strndup(text, i + 7);
  2604.         CopyMem("_lib.fd", to+i, 8);
  2605.       }
  2606.       if(!(out.file = Open(to, MODE_NEWFILE)) || !MakeFD(p))
  2607.         return 0;
  2608.     }
  2609.     else
  2610.     {
  2611.       while(p)
  2612.       {
  2613.         ULONG i;
  2614.         i = strlen(p->Basename) - 4;
  2615.         to = strndup(p->Basename, i+7);
  2616.         CopyMem("_lib.fd", to+i, 8);
  2617.         if(!(out.file = Open(to, MODE_NEWFILE)) || !MakeFD(p))
  2618.           return 0;
  2619.     Out(out.size); // free buffer
  2620.         Close(out.file);
  2621.         out.file = 0;
  2622.         p = (struct PragList *) p->List.Next;
  2623.       }
  2624.     }
  2625.   }
  2626.  
  2627.   if(CTRL_C)
  2628.     return 0;
  2629.   return 1;
  2630. }
  2631.  
  2632. STRPTR helptext =
  2633. "FDFILE:  the FD file which should be used\n"
  2634. "SPECIAL: 1 - Aztec compiler (xxx_lib.h,     MODE 2, AMICALL)\n"
  2635. "\t 2 - DICE compiler  (xxx_pragmas.h, MODE 3, LIBCALL)\n"
  2636. "\t 3 - SAS compiler   (xxx_pragmas.h, MODE 3, LIBCALL,LIBTAGS)\n"
  2637. "\t 4 - MAXON compiler (xxx_lib.h,     MODE 1, AMICALL)\n"
  2638. "\t 5 - STORM compiler (xxx_lib.h,     MODE 1, AMITAGS,AMICALL)\n"
  2639. "\t 6 - all compilers [default]\n"
  2640. "\t10 - assembler stub-functions assembler text\n"
  2641. "\t11 - assembler stub-functions link library\n"
  2642. "\t12 - defines and link library for local library base (register call)\n"
  2643. "\t13 - defines and link library for local library base (stack call)\n"
  2644. "\t20 - assembler lvo _lvo.i file\n"
  2645. "\t21 - assembler lvo _lib.i file\n"
  2646. "\t22 - assembler lvo _lvo.i file no XDEF\n"
  2647. "\t23 - assembler lvo _lib.i file no XDEF\n"
  2648. "\t24 - proto file with pragma/..._lib.h call\n"
  2649. "\t25 - proto file with pragma/..._pragmas.h call\n"
  2650. "\t26 - proto file with pragmas/..._lib.h call\n"
  2651. "\t27 - proto file with pragmas/..._pragmas.h call\n"
  2652. "\t28 - proto file with local/..._loc.h call\n"
  2653. "\t50 - FD file (source is a pragma file!)\n"
  2654. "TO:\t the destination directory (self creation of filename) or\n"
  2655. "\t the destination file\n"
  2656. "COMMENT: copy comments found in FD file\n"
  2657. "MODE:\t SPECIAL 1-6,AMICALL,LIBCALL,AMITAGS,LIBTAGS,CSTUBS:\n"
  2658. "\t 1 - _INCLUDE_PRAGMA_..._LIB_H definition method [default]\n"
  2659. "\t 2 - _PRAGMAS_..._LIB_H definition method\n"
  2660. "\t 3 - _PRAGMAS_..._PRAGMAS_H definition method\n"
  2661. "\t 4 - no definition\n"
  2662. "\t SPECIAL 10-13:\n"
  2663. "\t 0 - all functions, normal interface\n"
  2664. "\t 1 - only tag-functions, tagcall interface [default]\n"
  2665. "\t 2 - all functions, normal and tagcall interface\n"
  2666. "AMICALL: creates amicall pragmas\n"
  2667. "LIBCALL: creates libcall pragmas\n"
  2668. "AMITAGS: creates tagcall pragmas (amicall like method (StormC++))\n"
  2669. "LIBTAGS: creates tagcall pragmas (libcall like method (SAS C))\n"
  2670. "CSTUBS:  creates stub functions in C code\n"
  2671. "The last five need a string as argument. This string is used to set\n"
  2672. "a #if<given string> before the set method.\n"
  2673. "EXTERNC: add a #ifdef __cplusplus ... statement to pragma file\n"
  2674. "USESYSCALL: uses syscall pragma instead of libcall SysBase\n"
  2675. "CLIB:    name of the prototypes file in clib directory\n"
  2676. "PRIVATE: includes private declared functions\n"
  2677. "HEADER:  inserts given file into header of created file (\"\" is scan)\n"
  2678. "STORMFD: converts FD files of strange StormC++ format";
  2679.  
  2680. void main(void)
  2681. {
  2682.   ULONG mode = 0;
  2683.   ULONG spec = 0; // for default setting I need a ULONG var to get a pointer
  2684.   UBYTE filename[255];    // needed for filename
  2685.   struct
  2686.   {
  2687.     STRPTR FDFILE;
  2688.     ULONG* SPECIAL;
  2689.     STRPTR TO;
  2690.     ULONG  COMMENT;
  2691.     ULONG* MODE;
  2692.     STRPTR AMICALL;
  2693.     STRPTR LIBCALL;
  2694.     STRPTR AMITAGS;
  2695.     STRPTR LIBTAGS;
  2696.     STRPTR CSTUBS;
  2697.     ULONG  EXTERNC;
  2698.     ULONG  USESYSCALL;
  2699.     STRPTR CLIB;
  2700.     ULONG  PRIVATE;
  2701.     STRPTR HEADER;
  2702.     ULONG  STORMFD;
  2703.   } args = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  2704.  
  2705.   args.SPECIAL = &spec;
  2706.  
  2707. #ifdef __SASC    // with __MAXON__ this is done automatic by my StartUp
  2708.   TestOS;
  2709. #endif
  2710.  
  2711.   if(!(rda = (struct RDArgs *) AllocDosObject(DOS_RDARGS, 0)))
  2712.     End(RETURN_FAIL);
  2713.   rda->RDA_ExtHelp = helptext;
  2714.   if(!ReadArgs(PARAM, (LONG *) &args, rda))
  2715.     End(RETURN_FAIL);
  2716.  
  2717.   VPrintf("SourceFile: %s\n", &args.FDFILE);
  2718.  
  2719.   if(
  2720.   !(in.file = Open(args.FDFILE, MODE_OLDFILE)) ||
  2721.   !(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 37)) ||
  2722.   !(fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, 0)) ||
  2723.   !ExamineFH(in.file, fib) ||
  2724.   !(in.buf = in.pos = (STRPTR) AllocRemember(&remember, (in.size = fib->fib_Size)+1, MEMF_ANY)) ||
  2725.   Read(in.file, in.buf, in.size) != in.size ||
  2726.   !(out.buf = out.pos = (STRPTR) AllocRemember(&remember, out.size, MEMF_ANY)))
  2727.     End(RETURN_FAIL);
  2728.  
  2729.   {
  2730.     STRPTR ptr = FilePart(args.FDFILE);
  2731.     LONG len = strlen(ptr)-7;
  2732.     if(len >= 0 && !stricmp(ptr+len, "_lib.fd"))
  2733.     {
  2734.       ShortBaseName = ptr;
  2735.       ptr[len] = '\0';
  2736.     }
  2737.   }
  2738.  
  2739.   MakeLines(in.pos, in.size, 0);
  2740.  
  2741.   if(args.CLIB)
  2742.   {
  2743.     Close(in.file);
  2744.     if(!(in.file = Open(args.CLIB, MODE_OLDFILE)) ||
  2745.     !ExamineFH(in.file, fib) ||
  2746.     !(clibbuf = (STRPTR) AllocRemember(&remember, (clibsize = fib->fib_Size)+1, MEMF_ANY)) ||
  2747.     Read(in.file, clibbuf, clibsize) != clibsize)
  2748.       End(RETURN_FAIL);
  2749.     MakeLines(clibbuf, clibsize, 1);
  2750.   }
  2751.   Close(in.file); in.file = 0;
  2752.  
  2753.   if(args.TO)
  2754.   {
  2755.     if((lock = Lock(args.TO, SHARED_LOCK)) && Examine(lock, fib) &&
  2756.     fib->fib_DirEntryType > 0)
  2757.     {
  2758.       oldfh = CurrentDir(lock);
  2759.       args.TO = 0;
  2760.     }
  2761.     else if(lock)
  2762.     {
  2763.       UnLock(lock);
  2764.       lock = 0;
  2765.     }
  2766.   }
  2767.  
  2768.   if(*args.SPECIAL == 50)
  2769.   {
  2770.     STRPTR ptr = FilePart(args.FDFILE), ptr2;
  2771.  
  2772.     for(ptr2 = ptr; *ptr2 && *ptr2 != '_' && *ptr2 != '.'; ++ptr2)
  2773.       ;
  2774.     if(ptr2 != ptr)
  2775.     {
  2776.       ShortBaseName = ptr;
  2777.       *ptr2 = '\0';
  2778.     }
  2779.     if(!CreateFDFile(args.FDFILE, args.TO))
  2780.       End(RETURN_FAIL);
  2781.     End(RETURN_OK);
  2782.   }
  2783.  
  2784.   if(args.EXTERNC)        Flags ^= FLAG_EXTERNC;
  2785.   if(args.STORMFD)        Flags ^= FLAG_STORMFD;
  2786.   if(args.COMMENT)        Flags ^= FLAG_DOCOMMENT;
  2787.   if(args.PRIVATE)        Flags ^= FLAG_PRIVATE;
  2788.  
  2789.   if(!ScanFDFile())
  2790.     End(RETURN_FAIL);
  2791.  
  2792.   if(*args.SPECIAL < 10)
  2793.   {
  2794.     mode = MODUS_PRAGMA;
  2795.     sprintf(filename, "%s_lib.h", ShortBaseName);
  2796.  
  2797.     if(!args.LIBTAGS && !args.AMITAGS && !args.LIBCALL && !args.AMICALL &&
  2798.     !args.CSTUBS && !*args.SPECIAL)
  2799.       *args.SPECIAL = 6;
  2800.  
  2801.     switch(*args.SPECIAL)
  2802.     {
  2803.       case 0: break;
  2804.       case 1: MODE = 2; AMICALL = ""; break;
  2805.       case 2: sprintf(filename, "%s_pragmas.h", ShortBaseName);
  2806.               MODE = 3; LIBCALL = ""; Flags |= FLAG_PROTOTYPE; break;
  2807.       case 3: sprintf(filename, "%s_pragmas.h", ShortBaseName);
  2808.               MODE = 3; LIBCALL = ""; LIBTAGS = "def " TEXT_SAS_60; break;
  2809.       case 4: MODE = 1; AMICALL = ""; break;
  2810.       case 5: MODE = 1; AMICALL = AMITAGS = ""; break;
  2811.       case 6: MODE = 1; AMICALL = " defined(" TEXT_AZTEC ") || defined("
  2812.     TEXT_MAXON ") || defined(" TEXT_STORM ")";
  2813.     LIBCALL = " defined(" TEXT_DICE ") || defined(" TEXT_SAS ")";
  2814.     LIBTAGS = "def " TEXT_SAS_60; AMITAGS ="def " TEXT_STORM; break;
  2815.       default: mode = MODUS_ERROR;
  2816.     }
  2817.  
  2818.     if(args.AMICALL)        AMICALL = args.AMICALL;
  2819.     if(args.LIBCALL)        LIBCALL = args.LIBCALL;
  2820.     if(args.AMITAGS)        AMITAGS = args.AMITAGS;
  2821.     if(args.LIBTAGS)        LIBTAGS = args.LIBTAGS;
  2822.     if(args.CSTUBS)        CSTUBS = args.CSTUBS;
  2823.     if(args.USESYSCALL)        Flags ^= FLAG_SYSCALL;
  2824.  
  2825.     if(args.MODE && *args.MODE > 0 && *args.MODE < 5)
  2826.       MODE = *args.MODE;
  2827.   }
  2828.   else if(*args.SPECIAL < 20)
  2829.   {
  2830.     switch(*args.SPECIAL)
  2831.     {
  2832.     case 10: mode = MODUS_STUBTEXT;
  2833.       sprintf(filename, "%s_stub.a", ShortBaseName); break;
  2834.     case 11: mode = MODUS_STUBCODE;
  2835.       sprintf(filename, "%s.lib", ShortBaseName); break;
  2836.     case 12: Flags |= FLAG_LOCALREG; // no break !
  2837.     case 13: mode = MODUS_LOCALDATA;
  2838.       sprintf(filename, "%s_loc.h", ShortBaseName); args.TO = 0; break;
  2839.     default: mode = MODUS_ERROR;
  2840.     }
  2841.     if(args.MODE && *args.MODE >= 0 && *args.MODE < 3)
  2842.       MODE = *args.MODE;
  2843.   }
  2844.   else if(*args.SPECIAL < 30)
  2845.   {
  2846.     switch(*args.SPECIAL)
  2847.     {
  2848.     case 20: case 22: mode = MODUS_LVO+*args.SPECIAL-20;
  2849.       sprintf(filename, "%s_lvo.i", ShortBaseName); break;
  2850.     case 21: case 23: mode = MODUS_LVO+*args.SPECIAL-20;
  2851.       sprintf(filename, "%s_lib.i", ShortBaseName); break;
  2852.     case 24: case 25: case 26: case 27: case 28:
  2853.       mode = MODUS_PROTO+*args.SPECIAL-24;
  2854.       sprintf(filename, "%s.h", ShortBaseName); break;
  2855.     default: mode = MODUS_ERROR;
  2856.     }
  2857.   }
  2858.  
  2859.   if(mode == MODUS_ERROR)
  2860.   {
  2861.     SetIoErr(ERROR_TOO_MANY_ARGS);
  2862.     End(RETURN_FAIL);
  2863.   }
  2864.  
  2865.   if(!mode)
  2866.   {
  2867.     SetIoErr(ERROR_REQUIRED_ARG_MISSING);
  2868.     End(RETURN_FAIL);
  2869.   }
  2870.  
  2871.   if(!args.TO)
  2872.     args.TO = filename;
  2873.  
  2874.   if(args.HEADER)
  2875.   {
  2876.     if(!*args.HEADER)
  2877.       args.HEADER = args.TO;
  2878.     if(!(in.file = Open(args.HEADER, MODE_OLDFILE)) ||
  2879.     !ExamineFH(in.file, fib) ||
  2880.     !(HEADER = (STRPTR) AllocRemember(&remember, (headersize = fib->fib_Size)+1, MEMF_ANY|MEMF_CLEAR)) ||
  2881.     Read(in.file, HEADER, headersize) != headersize)
  2882.       End(RETURN_FAIL);
  2883.     if(args.HEADER == args.TO)
  2884.       FindHeader();
  2885.     Close(in.file);
  2886.     in.file = 0;
  2887.   }
  2888.  
  2889.   if(!(out.file = Open(args.TO, MODE_NEWFILE)))
  2890.     End(RETURN_FAIL);
  2891.  
  2892.   SetIoErr(0);
  2893.  
  2894.   if(mode == MODUS_PRAGMA)
  2895.     mode = CreatePragmaFile();
  2896.   else if(mode >= MODUS_PROTO)
  2897.     mode = CreateProtoFile(mode-MODUS_PROTO+1);
  2898.   else if(mode >= MODUS_LVO)
  2899.     mode = CreateLVOFile(mode-MODUS_LVO+1);
  2900.   else if(mode == MODUS_LOCALDATA)
  2901.     mode = CreateLocalData();
  2902.   else if(mode)
  2903.     mode = CreateAsmStubs(mode); // MODUS_STUBTEXT starts with 1
  2904.  
  2905.   if(!mode)
  2906.   {
  2907.     DoError(Output_Error ? ERR_UNKNOWN_ERROR : ERR_WRITING_FILE, 0);
  2908.     End(RETURN_FAIL);
  2909.   }
  2910.  
  2911.   End(RETURN_OK);
  2912. }
  2913.  
  2914. void end(void)
  2915. {
  2916.   if(fib)        FreeDosObject(DOS_FIB, fib);
  2917.   if(in.file)        Close(in.file);
  2918.   if(out.file)
  2919.   {
  2920.     Out(out.size);    // clears Output-Buffer
  2921.     Close(out.file);
  2922.   }
  2923.   if(oldfh)        CurrentDir(oldfh);
  2924.   if(lock)        UnLock(lock);
  2925.   if(remember)        FreeRemember(&remember, TRUE);
  2926.   if(IntuitionBase)    CloseLibrary((struct Library *) IntuitionBase);
  2927.   if(rda)
  2928.   {
  2929.     FreeArgs(rda);
  2930.     FreeDosObject(DOS_RDARGS, rda);
  2931.   }
  2932. }
  2933.